Solved

Floating Point Problem

Posted on 1998-12-30
22
318 Views
Last Modified: 2012-05-05
I have a C program that is running into problems rounding a float.  The calculation is as follows

//faceamt = 5000000 and rate = 205.07
premium = (faceamt / 1000) * rate;  
Round2Decimals(&premium);

//*******************************
void Round2Decimals(float *fn)
//********************************
{
 long lrd;
 double dg;
       dg = ceil (*fn * 100);
       if (dg - (double) *fn * 100 >= 0.51)
       dg -= 1.0;
       lrd = (long) dg;
       *fn = (float) lrd / 100;
}    

In the debugger, premium is calculated as 1.02535+e6 which appears to be correct.  This value is then passed to a function to round it to two decimals...
The problem is that dg ends up with 102535007 which is incorrect.  Where did the last two digits (07) come from and how can I avoid this without having to declare all variables as Doubles .  
Thanks.

Upon further investigation...
I think the problem is typecasting a float to a double.  
Example
float fltnum;
double dblnum;
fltnum = 205.07
dblnum = (double)fltnum;

//dblnum is now 205.07000732422.  This is what is causing the problems...
0
Comment
Question by:mtakasaki
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 5
  • 3
  • 3
  • +7
22 Comments
 

Author Comment

by:mtakasaki
ID: 1255487
Edited text of question
0
 
LVL 84

Expert Comment

by:ozo
ID: 1255488
keep all amounts in cents instead of dollars
0
 
LVL 3

Expert Comment

by:marcjb
ID: 1255489
Be careful that the multiplication by 100 doesn't overflow the lrd value.  1.02535e8 would cause a problem.
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 3

Expert Comment

by:marcjb
ID: 1255490
One other thing, is premium defined as a pointer or a float?
If it is a float, then the line
    Round2Decimals(premium);
is incorrect.  You would need
    Round2Decimals(&premium);

If it is a pointer, the line
    premium = (faceamt / 1000) * rate;  
is incorrect.  You would need
    *premium = (faceamt / 1000) * rate;  

Hope this helps

0
 

Author Comment

by:mtakasaki
ID: 1255491
Edited text of question
0
 

Author Comment

by:mtakasaki
ID: 1255492
Edited text of question
0
 
LVL 2

Expert Comment

by:ginde
ID: 1255493
If Possible Convert Float to Double.

This program works

#include <stdio.h>

#include <math.h>

    //*******************************
    void Round2Decimals(float *fn)
    //********************************
    {
     long lrd;
     double dg;
      dg = ceil (*fn * 100);
      if (dg - (double) *fn * 100 >= 0.51)
           dg -= 1.0;
      lrd = (long) dg;
      *fn = (float) lrd / 100;
    }    

void main()
{
float faceamt;
float rate;
float premium;

faceamt = (float)5000000;
rate = (float)205.07;
    premium = (faceamt / 1000) * rate;  
    Round2Decimals(&premium);
}
0
 
LVL 2

Expert Comment

by:ginde
ID: 1255494
As per my knowledge Float keeps only 7 digits intact, where as double keeps upto 15 digits. So you would be better off using double instead of float.

0
 

Author Comment

by:mtakasaki
ID: 1255495
Sorry but this did not work... in the debugger, premium has the value 1.02535+006 (which looks to be correct).  However, display this using a printf and the value is actually 1025350.0625.  This value is used when it is cast to a double (within the Round2Decimals() ).  
0
 
LVL 2

Expert Comment

by:ginde
ID: 1255496
You need to convert all float to Double to get it working. Please try this ( after conversion)

I think, Float is not reliable after 7 digits.


#include <stdio.h>

#include <math.h>

    //*******************************
    void Round2Decimals(double *fn)
    //********************************
    {
     long lrd;
     double dg;
      dg = ceil (*fn * 100);
      if (dg - (double) *fn * 100 >= 0.51)
           dg -= 1.0;
      lrd = (long) dg;
      *fn = (float) lrd / 100;
    }    

void main()
{
double faceamt;
double rate;
double premium;

faceamt = (double)5000000.00;
rate = (double)205.07;
    premium = (faceamt / 1000) * rate;  
    Round2Decimals(&premium);
}



0
 
LVL 10

Expert Comment

by:rbr
ID: 1255497
YOU HAVE TO USE DOUBLE SINCE YOU NEED MORE THAN 7 DIGITS.
Have you checked that your debugger display the full result of your variable. It looks to me that it uses a exponential format and displays only 6 digits.
0
 
LVL 10

Expert Comment

by:rbr
ID: 1255498
Your code will be even faster if you use double, since all functions in math.h are are double functions and you don't need to convert float to double all the time.
0
 

Author Comment

by:mtakasaki
ID: 1255499
Thanks for the suggestion to convert variables to doubles but I already knew that would help.  I'm looking for a way to deal with this problem without having to convert to doubles (i.e. possibly a compiler option???).
0
 
LVL 3

Expert Comment

by:a111a111a111
ID: 1255500
More points needed.
0
 
LVL 5

Expert Comment

by:scrapdog
ID: 1255501
I'll agree with ozo...it is best store all values as integers, then use a float for the result of the final calculation.
0
 
LVL 4

Expert Comment

by:jos010697
ID: 1255502
May I suggest the excellent article 'what every computer scientist should know about
floating point arithmetic', by David Goldberg (March 1991 Computing Surveys).

It carefully explains (among other useful stuff) what's happening when rounding,
converting and chopping floating point mantissas (significands).

kind regards,

Jos aka jos@and.nl
0
 
LVL 10

Expert Comment

by:rbr
ID: 1255503
Why don't you want to use double?
0
 
LVL 3

Expert Comment

by:a111a111a111
ID: 1255504
Any way. 50 points are not sufficient to my answer.
Sorry.

shayplace@hotmail.com
0
 
LVL 5

Expert Comment

by:scrapdog
ID: 1255505
Instead of saying what is not sufficient, why don't you name your price?  I presume that by making this statement, you have a correct and superior answer to all previous ones posted.
0
 
LVL 51

Expert Comment

by:ahoffmann
ID: 1255506
why do you expect exact values (7 digits) when casting incompatible types (long, float, double) ??
See jos' comment.
Also keep in mind that casting depends on the compiler, includes and  processor type.

BTW,
    fltnum = 205.07;
    dblnum = (double)fltnum;
check fltnum, and you will see that it is 205.07000732422 too.

If you want to know what really happens, you need to print the value bit by bit, not using
any libc routine which reads a bunch of bits/bytes.
Also make shure that the variables are set to zero before using.
0
 
LVL 1

Accepted Solution

by:
jim_pettinato earned 50 total points
ID: 1255507
Try this:

float RoundToNearestCent(float num)
{
  char buf[20];
  sprintf("%12.2f", num);
  return atof(buf);
}
0
 
LVL 1

Expert Comment

by:jim_pettinato
ID: 1255508
Oops.. error in my answer's sprintf statement.

should read sprintf(buf, "%12.2f", num);
                  * ___ *
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Preface I don't like visual development tools that are supposed to write a program for me. Even if it is Xcode and I can use Interface Builder. Yes, it is a perfect tool and has helped me a lot, mainly, in the beginning, when my programs were small…
This is a short and sweet, but (hopefully) to the point article. There seems to be some fundamental misunderstanding about the function prototype for the "main" function in C and C++, more specifically what type this function should return. I see so…
The goal of this video is to provide viewers with basic examples to understand recursion in the C programming language.
Video by: Grant
The goal of this video is to provide viewers with basic examples to understand and use for-loops in the C programming language.

707 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