C++ float to int - c++

Maybe, it's very simple question but I couldn't get the answer. I've been searching quite a while ( now Google think that I'm sending automated queries http://twitter.com/michaelsync/status/17177278608 ) ..
int n = 4.35 *100;
cout << n;
Why does the output become "434" instead of "435"? 4.35 * 100 = 435 which is a integer value and this should be assignable to the integer variable "n", right?
OR Does the C++ compiler cast 4.35 to integer before multiplying? I think it won't. Why does the compiler automatically change 4.35 to 4.34 which is still a float??
Thanks.

What Every Computer Scientist Should Know About Floating-Point Arithmetic
That's really just a starting point, sadly, as then languages introduce their own foibles as to when they do type conversions, etc. In this case you've merely created a situation where the constant 4.35 can't be represented precisely, and thus 4.35*100 is more like 434.9999999999, and the cast to int does trunc, not round.

If you run this statement:
cout << 4.35
Dollars to donuts you get something approximately like 4.3499998821 because 4.35 isn't exactly representable in a float.
When the compiler casts a float to an int it truncates.
To get the behavior your expect, try:
int n = floor((4.35 * 100.0) + 0.5);
(The trickyness with floor is because C++ doesn't have a native round() function)

The internal representation of 4.35 ends up being 4.349999999 or similar. Multiplying by 100 shifts the decimal, and the .9999 is dropped off (truncated) when converting to int.
Edit: Was looking for the link Nick posted. :)

Floating point numbers don't work that way. Many (most, technically an infinite number of...) values cannot be stored or manipulated precisely as floating point. 4.35 would seem to be one of them. It's getting stored as something that's actually below 4.35, hence your result.

When a float is converted to an int the fractional part is truncated, the conversion doesn't take the nearest int to the float in value.
4.35 can't be exactly represented as a float, the nearest representable number is (we can deduce) very slightly less that 4.35, i.e. 4.34999... , so when multiplied by 100 you get 434.999...
If you want to convert a positive float to the nearest int you should add 0.5 before converting to int.
E.g.
int n = (4.35 * 100) + 0.5;
cout << n;

Related

int conversion -- gives me weird numbers

I'm new to the programming world and C++ is already losing me. I had these lines in my program
pennies=(amount-nickels*.05)/.01;
amount is a double, while and nickels are int.
The program returns the right value when pennies is a double but things are a little off (off by 1 most of the time) whenever pennies is an int.
Why is this happening?
This is happening because the value is truncated thus losing the decimal precision.
For integers:
int i;
i = 1.1 //stores 1 in i
i = 1.2 //stores 1 in i
i = 1.3 //stores 1 in i
i = 1.4 //stores 1 in i
i = 1.5 //stores 1 in i
i = 1.6 //stores 1 in i
i = 1.7 //stores 1 in i
i = 1.8 //stores 1 in i
i = 1.9 //stores 1 in i
i = 1.999999 //stores 1 in i
I would suggest you to change your expression to:
pennies=amount*100-nickels*5;
As others have pointed out, the problem is because 0.1 and
0.05 don't have an exact representations in machine floating
point. The simplest solution here is to simply round the
results, instead of truncating:
pennies = round( (amount - nickels * 0.05) / 0.01 );
A better solution in this particular case (where you are dealing
with coins) is simply to use integers everywhere, and do
everything in terms of cents, rather than dollars. This stops
working (or requires some very complex programming) very quickly
however: even things like calculating VAT or sales tax cause
problems. For such cases, there are two possible solutions:
Continue using double, rounding as necessary. This is the
simplest and most general solution. Be aware, however, that
when using it, rounding is done on binary values, and it may
in some cases differ from what you would get with rounding
decimal values. The difference should be small enough that it
won't matter for every day use, but most countries have laws
specifying how such values must be rounded, and those rounding
rules are always specified in decimal. Which means that this
solution cannot be used in cases where legal requirements hold
(e.g calculating sales tax, corporate bookkeeping, etc.).
Use some sort of decimal class. There are a number available
on the network. This will result in slower execution times.
(Typically, who cares. You'll get the results in 100
microseconds, rather than 10. But there are exceptions; e.g.
when doing Monte Carlo simulations.)
Also, you must be aware when large values are involved. For
your personal finances, it's almost certainly irrelevant, but
int does have a maximum value, and there is a point where
double can no longer represent integer values correctly.
Of course, if this is just an exercise to help in learning C++,
just use round or integers, and don't worry too much about the
rest.
And as for your comment "C++ is already losing me": this has
nothing to do with C++ per se. You'd encounter exactly the same
issues in (almost) any programming language.
You compute a float number on the right part of the expression, but then you try to store a double in an int value. When you do this, the fractional part is lost.
pennies=(amount-nickels*.05)/.01;
In the above expression, the numerator and denominator arithmetic occurs in double because of the variable amount(which is double)-Implicit Conversion happens here. At the end if pennies is double the computed result will get stored in pennies, if it is int, fractional part of the computed result will be lost. The intermediate compution will always happens in double, and it doesn't depends upon pennies type anyway.
Example
#include <stdio.h>
int main()
{
int a ;
double c,d=10.55555;
a = c= (d+ 10*.5)/0.5 ;
printf("%f : %d/n",c,a);
return 0;
}
The output is:
31.111100 : 31
Here first 10 is promoted to float then 10*.5 will get evaluated, which will get promoted to double because of addition with a double value, then the denominator also converted to double as numerator is double, hence the compution occurs in double format only.

How to convert the double to become integer

It is hard to explain the question, i would like to convert a double number to integer without rounding the value after the decimal point.
For example
double a = 123.456
I want to convert become
int b = 123456
I want to know how many digit there is, and move it back after calculated to become 123.456
PS:I just want pure mathematical method to solve this issue, without calculating the character of it.
Sorry, there's no solution to your problem because the number 123.456 does not exist as a double. It's rounded to 123.4560000000000030695446184836328029632568359375, and this number obviously does not fit into any integer type after you remove the decimal point.
If you want 123.456 to be treated as the exact number 123.456, then the only remotely simple way to do this is to convert it to a string and remove the decimal point from the string. This can be achieved with something like
snprintf(buf, sizeof buf, "%.13f", 123.456);
Actually figuring out the number of places you want to print it to, however, is rather difficult. If you use too many, you'll end up picking up part of the exact value I showed above. If you use too few, then obviously you'll drop places you wanted to keep.
try this :
double a = 123.456;
int i;
char str[20];
char str2[20];
sptrintf(str,"%d",a);
for(i=0;i<strlen(str);i++)
{
if(!str[i] == '.')
{
sptrintf(str2,%c,str[i]);
}
}
int b = atoi(str2);
I believe the canonical way to do this would be
#include <math.h>
#include <stdio.h>
int main()
{
double d = 123.456;
double int_part;
double fract_part;
fract_part = modf(d, &int_part);
int i = (int)int_part*1000 + (int)(fract_part*1000);
printf("%d", i);
}
where the literal 1000 is a constant determining the number of desired decimals.
If you have the text "123.456" you can simply remove the decimal point and convert the resulting text representation to an integer value. If you have already converted the text to a floating-point value (double a = 123.456;) then all bets are off: the floating-point value does not have a pre-set number of decimal digits, because it is represented as a binary fraction. It's sort of like 1/3 versus .3333 in ordinary usage: they do not have the same value, even though we usually pretend that .3333 means 1/3.
Multiply each time original value with 10^i, increasing each time i until abs(value' - abs(value')) < epsilon for a very small epsilon. value' should be computed from the original each time, e.g.
value' = value * pow(10, i)
if ( abs(value' - abs(value')) < epsilon ) then stop
Originally I suggested that you should simply multiply by ten, but as R.. suggested, each time the numerical error gets accumulated. As result you might get a result of e.g. 123.456999 for an epsilon = .0000001 instead of 123.456000 due to floating point math.
Please note that you might exceed int type boundaries this way and might want to handle infinity values as well.
As Ignacio Vazquez-Abrams noted this might lead to problems with scenarios where you want to convert 123.500 to 123500. You might solve it by adding a very small value first (and it should be smaller than epsilon). Adding such a value could lead to a numeric error though.

How to check if float is a whole number?

The printf function's %g is able to show the whole number 3 if the float is 3.00, and will show 3.01 if the float's value isn't a round number float.
How would you do this yourself through some code, without formatting the number as a string?
There isn't really a simple answer
Integral values do have exact representations in the float and double formats. So, if it's really already integral, you can use:
f == floor(f)
However, if your value is the result of a calculation which at one point involved any sort of non-zero fractional part, then you will need to be concerned that you may have something very close to an integer but which isn't really, exactly, to-the-last-bit the same. You probably want to consider that to be integral.
One way this might be done:
fabs(f - round(f)) < 0.000001
And while we are on the subject, for the purists, we should note that int i = f; or double i = f; will round according to the FPU mode whereas round(3) will round half-way cases away from zero.

Precision of Floats to Ints vs Doubles to Ints, unexpected results

I am computer engineering student and do tutoring for the introductory C++ classes at BYU-Idaho, and a student successfully stumped me.
If write the code for this:
#include <iostream>
using namespace std;
int main()
{
float y = .59;
int x = (int)(y * 100.0);
cout << x << endl;
return 0;
}
Result = 58
#include <iostream>
using namespace std;
int main()
{
double y = .59;
int x = (int)(y * 100.0);
cout << x << endl;
return 0;
}
Result = 59
I told him it was a precision issue and that because the int is more precise than a float it loses information. A double is more precise than a float so it works.
However I am not sure if what I said is correct. I think it has something to do with the int getting padded with zeros and as a result it gets "truncated" while it get's casted, but I am not sure.
If any of you guys want to explain what is going on "underneath" all of this I would find it interesting!
The problem is that float isn't accurate enough to hold the exact value 0.59. If you store such a value, it will be rounded in binary representation (already during compile time) to something different, in your case this was a value slightly less than 0.59 (it might also be slightly greater than the value you wanted it to be). When multiplying this with 100, you get a value slightly less than 59. Converting such a value to an integer will round it towards 0, so this leads to 58.
0.59 as a float will be stored as (now being represented as a human-readable decimal number):
0.589999973773956298828125
Now to the double type. While this type has essentially the same problem, it might be of two reasons why you get the expected result: Either double can hold the exact value you want (this is not the case with 0.59 but for other values it might be the case), or the compiler decides to round it up. Thus, multiplying this with 100 leads to a value which is not less than 59 and will be rounded towards 0 to 59, as expected.
Now note that it might be the case that 0.59 as a double is still being rounded down by the compiler. Indeed, I just checked and it is. 0.59 as a double will be stored as:
0.58999999999999996891375531049561686813831329345703
However, you are multiplying this value with 100 before converting it to an integer. Now there comes an interesting point: When multiplied with 100, the difference of y to 0.59 put by the compiler is eliminated since 0.59 * 100 can again not be stored exactly. In fact, the processor calculates 0.58999999999999996891375531049561686813831329345703 * 100.0, which will be rounded up to 59, a number which can be represented in double!
See this code for details: http://ideone.com/V0essb
Now you might wonder why the same doesn't count for float, which should behave exactly the same but with different accuracy. The problem is that 0.589999973773956298828125 * 100.0 is not rounded up to 59 (which can also be represented in a float). The rounding behavior after calculations isn't really defined.
Indeed, operations on floating point numbers aren't exactly specified, meaning that you can encounter different results on different machines. This makes it possible to implement performance tweaks which lead to slightly incorrect results, even if rounding isn't involved! It might be the case that on another machine you end up with the expected results while on others you are not.
0.59 is not exactly representable in binary floating-point. So x will actually be a value very slightly above or below 0.59. Which it is may be affected by whether you use float or double. This in turn will determine whether the result of your program is 58 or 59.
It is a precision issue, and has to do with the fact that .59
is not exactly representable in either a double or a float.
So y is not .59; it is something very close to .59
(slightly more or slightly less). The multiplication by 100
is exact, but since the original value wasn't, you get something
slightly more or slightly less than 59. Conversion to int
truncates to zero, so you get either 59 or 58.
This is the same problem as when you use an old calculator to do 1 / 3 * 3, and it comes up with 2.9999999 or something similar. Combine this with the fact that the (int)(float_value) will simply chop the decimals of, so if floatvalue is 58.999996185 like my machine gets, then 58 will be the result, because although 58.999996185 is NEARLY 59, if you cut out only the first two digits, it is indeed 58.
Floating point numbers are great for calculating a lot of things, but you have to be VERY careful when it comes to "what is the result". It is an approximation, the precision is not infinite, and rounding of intermediate results will happen.
With double, there are more digits, and it may well be that when the calculation of 0.58999999999999 times 100, the last bit is a one instead of a zero, so the result is a 59.00000000001 or something like that, whcih then becomes 59 as an integer.

multiplication of double with integer precision

I have a double of 3.4. However, when I multiply it with 100, it gives 339 instead of 340. It seems to be caused by the precision of double. How could I get around this?
Thanks
First what is going on:
3.4 can't be represented exactly as binary fraction. So the implementation chooses closest binary fraction that is representable. I am not sure whether it always rounds towards zero or not, but in your case the represented number is indeed smaller.
The conversion to integer truncates, that is uses the closest integer with smaller absolute value.
Since both conversions are biased in the same direction, you can always get a rounding error.
Now you need to know what you want, but probably you want to use symmetrical rounding, i.e. find the closest integer be it smaller or larger. This can be implemented as
#include <cmath>
int round(double x) { std::floor(x + 0.5); } // floor is provided, round not
or
int round(double x) { return x < 0 ? x - 0.5 : x + 0.5; }
I am not completely sure it's indeed rounding towards zero, so please verify the later if you use it.
If you need full precision, you might want to use something like Boost.Rational.
You could use two integers and multiply the fractional part by multiplier / 10.
E.g
int d[2] = {3,4};
int n = (d[0] * 100) + (d[1] * 10);
If you really want all that precision either side of the decimal point. Really does depend on the application.
Floating-point values are seldom exact. Unfortunately, when casting a floating-point value to an integer in C, the value is rounded towards zero. This mean that if you have 339.999999, the result of the cast will be 339.
To overcome this, you could add (or subtract) "0.5" from the value. In this case 339.99999 + 0.5 => 340.499999 => 340 (when converted to an int).
Alternatively, you could use one of the many conversion functions provided by the standard library.
You don't have a double with the value of 3.4, since 3.4 isn't
representable as a double (at least on the common machines, and
most of the exotics as well). What you have is some value very
close to 3.4. After multiplication, you have some value very
close to 340. But certainly not 399.
Where are you seeing the 399? I'm guessing that you're simply
casting to int, using static_cast, because this operation
truncates toward zero. Other operations would likely do what
you want: outputting in fixed format with 0 positions after the
decimal, for example, rounds (in an implementation defined
manner, but all of the implementations I know use round to even
by default); the function round rounds to nearest, rounding
away from zero in halfway cases (but your results will not be
anywhere near a halfway case). This is the rounding used in
commercial applications.
The real question is what are you doing that requires an exact
integral value. Depending on the application, it may be more
appropriate to use int or long, scaling the actual values as
necessary (i.e. storing 100 times the actual value, or
whatever), or some sort of decimal arithmetic package, rather
than to use double.