# Pls help.. inconsistent integer conversion

Hi guys,
I am out of points so pls. try to help ;)
I have a double which I want to typecast to an int
ie. = double ret ;
int i;
ret = ..... some calculation (using floor/ceil/pow);
i = (int) ret;

Then problem is that I printed out both ret and i:
ret = 510 BUT i = 509  !!!!!!! inconsistent
why is the convesion inconsistent and HOW do i solve it?
I tried typecaseting it to a long int but it is still the same....
Pls. help.. thanks!!!

David

LVL 1
###### Who is Participating?

Commented:
The problem is that the conversion rounds down (as warren_dale implies).  If you really do want to round a floating point number (float or double) to the *nearest* integer (int or long), just add 0.5 before you do the conversion, eg.

float number = 0.9999f;
int nearestInt = (int)(number + 0.5f);

0.9999 + 0.5 = 1.4999, which will get rounded down to 1 in the conversion.

0

Commented:
#include <stdio.h>
int main(void)
{
float r;
int i;
r = 509.9;
i = r;
printf("%5.0f\n", r);
printf("%7.1f\n", r);
printf("%5d\n", i);
return 0;
}
when executed produces
510
509.9
509
In other words the "i = r;" truncates, but the "printf("%5.0f\n", r);" rounds.
Is this clear?
0

Author Commented:
yes, but my answer should be 510 , not 509
when I print it out as double , it reads 510.0
so by right, if I convert it to integer , it should also be 510 and not 509.
Pls. note that the 510 val is computed and not assigned.

0

Commented:
What is the actual value?
What source code do you use that prints out the value as 510?
0

Commented:
double r;
int i;
r = -1e-4;
r += 510;
i = r;
printf("%.20f\n", r);
printf("%.1f\n", r);
printf("%d\n", i);
0

Author Commented:
actually I'm using a rounding function:
fround(n,d) ((floor((n) * pow(10.,(d))) / pow(10. ,(d)))
which is a rounding down function.

and I used it to calculate addition of 2 numbers, a + b
a = fround( value1, nodec);
b = fround (value2, nodec);
1)   result  =  a+ b;
after which I round the final answer ( i have a few rounding variations,
round adjust, round up, down,... )
2) result = fround ( result, nodec);

From 1) where a = b= 2.555 and nodec = 2, my answer after 1) is result = 5.10
(I printed it out as a double) BUT after 2) where it is rounded again,
it comes out as 509 ( I printed it again )..
u see my problem?? :)
So I wrote my own myfloor function which returns a double as a integer,
basically doing a rounding down by : return (int) doublevalue;
and I printed out both 3) doublevalue and 4) (int) doublevalue
by the same values entered , 3) = 510 and 4) gives me 509... again the same problem!!!

Hope that explains how I got the problem.. thanks guys and keep those comments coming in..!!!

David

0

Commented:
#include <stdio.h>
#include <math.h>
int main(void){
double r;
int i;
r = 255.0/100.0 + 255.0/100.0;
i = r;
printf("%.20f\n", r);
printf("%.1f\n", r);
printf("%d\n", i);
r *= 100;
i = r;
printf("%.20f\n", r);
printf("%.2f\n", r);
printf("%d\n", i);
return 0;
}
when executed produces
5.09999999999999960000
5.10
5
509.99999999999994000000
510.00
509

0

Author Commented:
to ozo: thanks!!!
so it basically boils down to the fact that double does some rounding up (depending on the decimal val) while integer just truncates it..  : )
I guess that gbeau (thanks) answer should solve this problem ie. (int)(value + 0.5)
what do u think?? Is it a good solution to this problem or is there another way?
I remember a similar prob in MFC and I used _fcvt to work round it..  ;) But then, this is Unix.
0

Commented:
printf %f does rounding.
(int) just truncates
(double) is only approximate

(int)(value + 0.5)
only works if value > -0.5
0

Author Commented:
what bout negative values then??
check the if condition and do (int)(val - 0.5)?
Until now, there has been no clear solution to my problem...
:( I know the why but I am still looking for the how..
anyway, the solution must be reliable ..
0

Commented:
> check the if condition and do (int)(val - 0.5)?
That can be ok if val is int he range of an int.
floor(val+0.5) may be a better choice in general.
(although you may prefer a true round-to-even if you;re woring with decimal representations)
or if you need more precise control over exact values, you may even want to to all your calculations using int
0

Author Commented:
that comes back to round one...
my rounding down (or up) for FP function is:
rounddown = floor( FPvalue * pow(10,dec) )/(pow(10,dec))
by doing the above:
floor( val + 0.5) ; it is not a rounding down func anymore..
it is a normal rounding adjust func which is not what I need ..
by doing the above ...
:)

0

Commented:
No matter what you do, there will always exist values which are not exactly represetable as a (double)
255.0/100.0 is one such value
and any code which depends on 255.0/100.0 being exactly represented in a (double) is faulty
If you don't need to distinguish numbers between, say 254999.0/100000.0 and 255001.0/100000.0
then you may be able write your code in a way that treats all numbers in that range the same.
If you don't mind your rounddown value only being accurate within  1/(pow(10,dec), you might use something like
(floor( FPvalue * pow(10,dec))+0.1 )/(pow(10,dec))
and be able to repeatedly apply the function without accumulating additional error.
But if you need be able to distingush, say
254999999999999999/100000000000000000 from 255000000000000001/100000000000000000
then you may not be able to do it in a (double)
If so, perhaps your needs may be better served with some sort of extended precision data type.
Or if you know you always want all your values exact to two decimal places,
then instead of dealing with (double)5.10 which is not exact,
you might instead always deal internally with (int)510 which is exact.
0

Author Commented:
Yes, I really need be able to distingush
254999999999999999/100000000000000000 from
255000000000000001/100000000000000000
and the fact that my decimal representation is not fixed means that there really is
no perfect solution to my prob. :(
Extended precision data type? Maybe but I have no idea how. Perhpas a hint?? ;)
Ozo .. thank u for explaining all that to me and I think u really deserve a lot more points than zero.. :)
Tell u what, give a dummy answer to another question that I have (150 points) that so far so one has answered well and I will give those 150 points to u that u deserve for helping me here...  cause the other question is not needed by me now.
Thanks again and feel free to post any more comments on this....

Ps. right now I am trying out a string rounding function that seems to work well ( exact anyway ).. it may be slow and inefficient but at least I know that the result are always consistent cause I am using the nos for financial calculations....

David

0

Commented:
> Yes, I really need be able to distingush
>           254999999999999999/100000000000000000 from
>           255000000000000001/100000000000000000
So you need at least 18 digits worth of precision,
Do you know how much precision will be required in all?

If you don't want to write your own multiple precision routines,
you might try using GNU MP library, or, if you're on a unix system, you may be able to just fork a `dc` process to do the arithmetic.
0