C++ Handling Ints and Floats

01
of 08

All About Numbers in C++

In C++ there are two types of numbers. Ints and floats. There are also variants of these types that hold bigger numbers, or only unsigned numbers but they are still ints or floats.

An int is a whole number like 47 without a decimal point. You can't have 4.5 babies or loop 32.9 times. You can have $25.76 if you use a float. So when you create your program, you must decide which type to use.

Why not Just Use Floats?

This is what some scripting languages do? Because it's inefficient, floats take up more memory and are generally slower than ints. Also, you cannot easily compare two floats to see if they are equal like you can with ints.

To manipulate numbers you have to store them in memory. Because the value can be easily changed, it's called a variable.

The compiler that reads your program and converts it into machine code needs to know what type it is, i.e. whether it's an int or a float, so before your program uses a variable, you must declare it.

Here's an example.

 

 int Counter =0;
 float BasicSalary; 

You'll notice that the Counter variable is set to 0. This is an optional initialization. It's a very good practice to initialize variables. If you don't initialize and then use them in code without having set an initial value, the variable will start with a random value that may 'break' your code. The value will be whatever was in memory when the program was loaded.

02
of 08

More about Ints

What is the biggest number an int can store?. Well, it depends on the type of CPU but it is generally accepted as 32 bits. Because it can hold almost as many negative values as positive, the range of values is +/- 2-32 to 232 or -2,147,483,648 to +2,147,483,647.

This is for a signed int, but there is also an unsigned int that holds zero or positive. It has a range of 0 to 4,294,967,295. Just remember - unsigned ints don't need a sign (like + or -1) in front of them because they are always positive or 0.

Short Ints

There is a shorter int type, coincidentally called short int which uses 16 bits (2 bytes). This holds numbers in the range -32768 to +32767. If you use a large umber of ints, you can possibly save memory by using short ints. It will not be any quicker, despite being half the size. 32 Bit CPUs fetch values from memory in blocks of 4 bytes at a time. I.e. 32 bits (Hence the name- 32 Bit CPU!). So fetching 16 bits still requires a 32 bit fetch.

There is a longer 64 bit called long long in C. Some C++ compilers while not supporting that type directly use an alternate name- e.g. both Borland and Microsoft use _int64. This has a range of -9223372036854775807 to 9223372036854775807 (signed) and 0 to 18446744073709551615 (unsigned).

As with ints there is an unsigned short int type that has a range of 0..65535.

Note: Some computer languages refer to 16 bits as a Word.

03
of 08

Precision Arithmetic

Double Trouble

There's no long float, but there is a double type that is twice as big as float.

  • Float: Occupies 4 bytes. Range 17x10-38 to 1.7x1038
  • Double: Occupies 8 bytes. Range 3.4x10-308 to 3.4308

Unless you're doing scientific programming with very large or small numbers, you'll only use doubles for greater precision. Floats are good for 6 digits of accuracy but doubles offer 15.

Precision

Consider the number 567.8976523. It is a valid float value. But if we print it out with this code below you can see lack of precision appearing. The number has 10 digits but is being stored in a float variable with only six digits of precision.

 

 #include <iostream>
 using namespace std;
 int main(int argc, char* argv[])
 {
 float value = 567.8976523;
 cout.precision(8) ;
 cout << value << endl;
 return 0;
 }
 

See About Input and Output for details on how cout works, and how to use precision. This example sets the output precision to 8 digits. Unfortunately floats can only hold 6 and some compilers will issue a warning about converting a double to a float. When run, this prints out 567.89764

If you change the precision to 15, it prints as 567.897644042969. Quite a difference! Now move the decimal point two to the left so the value is 5.678976523 and rerun the program. This time it outputs 5.67897653579712. This is more accurate but still different.

If you change the type of value to double and the precision to 10 it will print the value exactly as defined. As a general rule, floats are handy for small, non integer numbers but with more than 6 digits, you have to use doubles.

04
of 08

Learn about Arithmetic Operations

Writing computer software wouldn't be much use if you couldn't do addition, subtraction etc. Here's example 2.

 // ex2numbers.cpp 
 //
 #include <iostream>
 
 using namespace std;
 
 int main()
 {
 int a=9;
 int b= 12;
 int total=a+b;
 cout << "The total is " << total << endl;
 
 return 0;
 }
 

 

Explanation of Example 2

Three int variables are declared. A and B are assigned values, then total is assigned the sum of A and B.

Before running this example

Here's a little tip to save time when running Command Line applications.

When you run this program from the Command Line, it should output "The number is 22".

Other Arithmetic Operations

As well as addition, you can do subtraction, multiplication and division. Just use + for addition, - for subtraction, * for multiplication and / for division.

Try changing the above program- use subtraction or multiplication. You can also change ints to floats or doubles.

With floats, you have no control over how many decimal points are displayed unless you set the precision as shown earlier.

05
of 08

Specifying Output Formats with cout

When you're outputting numbers, you need to think about these attributes of the numbers.

  • Width- How much space is needed for the entire number
  • Alignment - left or right- numbers tend to be right aligned
  • Number of decimal places
  • Sign or brackets for negative numbers.
  • Thousands Separators. Big numbers look ugly without these.

Now width, alignment, number of decimal places and signs can be set by the cout object and iomanip include file functions.

Thousands separators are a little more complicated. They are set from the locale of a PC. A locale contains information relevant to your country- such as currency symbols and decimal point and thousands separators. In the UK and USA, the number 100.98 uses a decimal point . as the decimal point whereas in some European countries it is a comma so €5,70 means a price of 5 Euros and 70 cents.

 int main()
 {
 double a=925678.8750;
 cout.setf(ios_base::showpoint|ios_base::right) ;
 cout.fill('=') ;
 cout.width(20) ;
 locale loc("") ;
 cout.imbue( loc ) ; 
 cout.precision(12) ;
 cout << "The value is " << a << endl;
 
 //cout.unsetf(ios_base::showpoint) ;
 cout << left << "The value is " << a << endl;
 
 for (int i=5;i< 12;i++) {
 cout.precision(i) ;
 cout << setprecision(i)<< "A= " << a << endl;
 }
 
 const moneypunct <char, true> &mpunct = use_facet <moneypunct <char, true > >(loc) ;
 
 cout << loc.name( )<< mpunct.thousands_sep( ) << endl;
 return 0;
 }
 

The output from this is

 =======The value is 925,678.875000
 The value is 925,678.875000
 A= 9.2568e+005
 A= 925,679.
 A= 925,678.9
 A= 925,678.88
 A= 925,678.875
 A= 925,678.8750
 A= 925,678.87500
 English_United Kingdom.1252,
 

06
of 08

About Locale and Moneypunct

The example used a locale object from the PC in the line

 locale loc("") ; 

The line

 const moneypunct <char, true> &mpunct = use_facet <moneypunct <char, true > >(loc) ;
 

creates an object mpunct which is a reference to a moneypunct template class. This has information about the specified locale - in our case, the thousands_sep() method returns the character used for thousands separator.

Without the line

 cout.imbue( loc ) ; 

There would be no thousand's separators. Try commenting it out and rerunning the program.

Note There seem to be discrepancies between different compilers as to how cout.imbue behaves. Under Visual C++ 2005 Express Edition, this included separators. But the same code with Microsoft Visual C++ 6.0 did not!

Decimal Points

The example on the previous page used showpoint to show trailing zeros after the decimal points. It output numbers in what is called standard mode. Other modes include

  • Fixed Mode - Show numbers like 567.8
  • Scientific Mode - Show numbers like 1.23450e+009

If you use either of these two formatting modes through the cout.setf then precision() sets the number of decimal places after the decimal point (not the overall number of digits) but you lose the thousands formatting. Also trailing zeroes (as were enabled by ios_base::showpoint ) become automatically enabled without needing showpoint.

07
of 08

Things to Watch out for with ints, floats and bools

Take a look at this statement.

 float f = 122/11; 

You'd expect something like a value of 11.0909090909. In fact, the value is 11. Why is this? because the expression on the right-hand side (known as an rvalue) is integer/integer. So it uses integer arithmetic which throws away the fractional part and assigns 11 to f. Changing it to

 float f = 122.0/11 

will correct it. It's a very easy gotcha.

Types Bool and Int

In C, there is no such type as a bool. Expressions in C were based on a zero being false or a non-zero being true. In C++ the type bool can take the values true or false. These values are still equivalent to 0 and 1. Somewhere in the compiler it will have a

 const int false=0;
 const int true= 1;
 

Or at least it acts that way! The two lines below are valid without casting so behind the scenes, bools are implicitly converted to ints and can even be incremented or decremented though this is very bad practice.

 bool fred=0;
 int v = true;
 

Look at this code

 bool bad = true;
 bad++
 if (bad) ...
 

The if will still do the if as the bad variable is non-zero but it is bad code and should be avoided. Good practice is to use them as they are intended. if (!v) is valid C++ but I prefer the more explicit if (v != 0). That, however, is a matter of taste, not a must-do directive.

08
of 08

Use Enums for Better Code

For a more in depth look at enums, read this article first.

An enum is another type that is based on int.

An enum type provides a way to restrict a variable to one of a fixed set of values.

 enum rainbowcolor {red,orange,green, yellow, blue,indigo,violet};
 

By default these are assigned the values 0 to 6 (red is 0, violet is 6). You can define your own values instead of using the compiler values e.g.

 enum rainbowcolor {red=1000,orange=1005,green=1009, yellow=1010, blue,indigo,violet};
 

The remaining unassigned colors will be assigned 1011, 1012 and 1013. The values continue sequentially from the last assigned value which was

yellow=1010

.

You can assign an enum value to an int as in

 int p=red; 
 

but not the other way round. That's the restriction and it prevents assignment of meaningless values. Even assigning a value that corresponds to an enum constant is an error.

 rainbowcolor g=1000; // Error!
 

The requires

 rainbowcolor g=red;
 

This is

type safety

in action. Only valid values of the enumeration range can be assigned. This is part of the general C++ philosophy that

it is better for the compiler to catch errors at compile time than the user at runtime

.

Even though the two statements are conceptually the same. In fact you'll usually find that these two seemingly identical lines

 int p =1000;
 rainbowcolor r = red;
 

are both likely to have identical machine code generated by the compiler. Certainly they do in Microsoft Visual C++.

That completes this tutorial. The next tutorial is about expressions and statements.