Solved

Pls help.. inconsistent integer conversion

Posted on 1998-09-20
15
282 Views
Last Modified: 2010-04-15
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
   
     
0
Comment
Question by:Haho
  • 6
  • 6
  • 2
  • +1
15 Comments
 
LVL 1

Expert Comment

by:warren_dale
ID: 1252910
#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
 

Accepted Solution

by:
gbeau earned 0 total points
ID: 1252911
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
 
LVL 1

Author Comment

by:Haho
ID: 1252912
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
 
LVL 1

Expert Comment

by:warren_dale
ID: 1252913
What is the actual value?
What source code do you use that prints out the value as 510?
0
 
LVL 84

Expert Comment

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

Author Comment

by:Haho
ID: 1252915
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
 
LVL 84

Expert Comment

by:ozo
ID: 1252916
#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
Do You Know the 4 Main Threat Actor Types?

Do you know the main threat actor types? Most attackers fall into one of four categories, each with their own favored tactics, techniques, and procedures.

 
LVL 1

Author Comment

by:Haho
ID: 1252917
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
 
LVL 84

Expert Comment

by:ozo
ID: 1252918
printf %f does rounding.
(int) just truncates
(double) is only approximate

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

Author Comment

by:Haho
ID: 1252919
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
 
LVL 84

Expert Comment

by:ozo
ID: 1252920
> 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
 
LVL 1

Author Comment

by:Haho
ID: 1252921
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
 
LVL 84

Expert Comment

by:ozo
ID: 1252922
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
 
LVL 1

Author Comment

by:Haho
ID: 1252923
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
 
LVL 84

Expert Comment

by:ozo
ID: 1252924
> 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

Featured Post

Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

Join & Write a Comment

Have you thought about creating an iPhone application (app), but didn't even know where to get started? Here's how: ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ ~ Important pre-programming comments: I’ve never tri…
An Outlet in Cocoa is a persistent reference to a GUI control; it connects a property (a variable) to a control.  For example, it is common to create an Outlet for the text field GUI control and change the text that appears in this field via that Ou…
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use while-loops in the C programming language.
The goal of this video is to provide viewers with basic examples to understand how to create, access, and change arrays in the C programming language.

757 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now