Computing.Net > Forums > Programming > Slight inaccuracy Rounding Problem

Computer Problems? Computing.Net has over 1,000,000 posts about all things technology related! Over 90% answered within 24 hours! Click here to start participating now! Also, be sure to check out the New User Guide.

Slight inaccuracy Rounding Problem

Reply to Message Icon

Name: cool_andy
Date: December 11, 2007 at 02:44:01 Pacific
OS: Windows XP
CPU/Ram: 512
Product: Acer
Comment:

Ok I have implemented the following function to round figures ".5" up instead of down.
float Round_float(float value)
{
char roundtest[40];
char *position = roundtest;


value += 0.00500001;


sprintf(roundtest,"%lf",value);

while ( *position != 0 )
{
if ( *position == '.')
{
*(position + 3) = 0;
/*replace 3rd decimal place with null*/
break;
}

position++;
}

return atof(roundtest);

}

This returns a 2.d.p figure. To test it I have done the following:
float test = 11.5549999;

test = Round_float(test);
printf("test = %.2f\n",test);

The figure is 11.56 in error. It should have been 11.55.
However if the test variable was 1 decimal place less than above 11.554999 (6.d.p). The figure is rounded to 11.55 correctly.

In my program I have many net price percentage increases which at the moment appear to be correctly rounded. Although the scenario above is unlikely to occur, I am justing wonder how to solve the slight inaccuracy above (7.d.p or more).

I have also just realised that 11.549999 plus 0.00500001 becomes 11.56. So only 0.005 is needed to be added on in this scenario case?



Sponsored Link
Ads by Google

Response Number 1
Name: Razor2.3
Date: December 11, 2007 at 06:22:56 Pacific
Reply:

Welcome to the amazing world of binary math, where

cos(x) != cos(y) && x == y

Sometimes it makes me think COBOL had it right, with its base 10 math.

0

Response Number 2
Name: StuartS
Date: December 11, 2007 at 06:32:46 Pacific
Reply:

If you want to round up to 2 decimal points then just add .005 in all circumstances.

.5 will round up the nearest integer with the fraction discarded.
.05 to one decimal point with digits over one discarded.
.005 to two decimal points with digits over two discarded.
.0005 to three decimal points with digits over three discarded.

add infinitum.

Stuart


0

Response Number 3
Name: klint
Date: December 11, 2007 at 11:48:30 Pacific
Reply:

Your method of truncating the non-significant digits, by converting to a string and back again, is very compute-intensive. Better to multiply by 100, 1000, etc., then truncate to its integer part using a suitable run-time library function, and divide by 100 or 1000. Also, instead of adding .5 and truncating, why not use the round() function?

For full details of rounding, see

http://en.wikipedia.org/wiki/Rounding

Also, if you really get into the subject, read "What every computer scientist should know about floating-point arithmetic":

http://docs.sun.com/source/806-3568...
http://www.physics.ohio-state.edu/~...


0

Response Number 4
Name: cool_andy
Date: December 12, 2007 at 03:11:17 Pacific
Reply:

Ok, if I add on just 0.005 to 11.5549999 its becomes 11.560000.
I would expect it to become 11.5599999 before truncating.
Is this possibly because floating point figures have a limit of 6.d.p? "%f" always displays six decimal figures.

Also I do not have access to trunc() and round() in the math.h library. I am using C. Are they standard C++ library functions?
Alternatively it would be useful to know a different truncate programming method than removing the 3rd decimal place in the string as above.

Thanks for your help

Andrew


0

Response Number 5
Name: klint
Date: December 12, 2007 at 06:54:41 Pacific
Reply:

When you add 0.005 to 11.5549999, it does not become 11.56000. It just appears to, when you print it. Floating-point numbers are not represented the same way internally as they are when printed in base 10.

The "%f" format can display to any precision you like; just specify it. If you want 10 dp, use "%.10f" It only prints 6dp by default because it's unusual that you would want more than than in typical circumstances.

The trunc() and round() functions are part of the ISO Standard C 99 language. If you are using a Microsoft compiler, it's unlikely that they've implemented that standard yet; you are probably still using the ISO C 90 standard. You can round the number to 2 dp by using this expression:

(f + 0.005) - fmod(f + 0.005, 0.01)

Alternatively, and a little closer to the method I mentioned in my earlier post:

((long)(f * 100 + 0.5) / 100


0

Related Posts

See More



Response Number 6
Name: cool_andy
Date: December 12, 2007 at 07:53:58 Pacific
Reply:

Ok after using both my string method and your method above.
I still get the answer 11.56 rounded from 11.5549999 incorrectly.
If I use printf to specify 7.d.p "%.7f"
it displays (after adding 0.005):
11.5600004.
For some reason that appears to be an error margin of 0.0000005 (7.d.p).
Simliarly if I use printf to specify 8.d.p "%.8f" it displays:
11.56000042 (error margin = 0.00000052)

I just trying to understand why these figures above are appearing using printf.
However I only consider this a minor issue, and you have helped me learned a little more about rounding.
Thanks again for your advice
Andrew



0

Response Number 7
Name: klint
Date: December 12, 2007 at 09:02:21 Pacific
Reply:

When I do:

fprintf("%12.8f", 11.5549999 + 0.005);

I get 11.55999990, as you would expect. You get 11.56 when you printf("%f",...) because that rounds the displayed value to 6dp.

I have no idea why you get 11.5600004. That's strange. Could it be that you are sprintf'ing to 6dp and then converting back to 7dp, thus losing significant figures?


0

Response Number 8
Name: StuartS
Date: December 12, 2007 at 09:10:26 Pacific
Reply:

You want it rounded up to 2 decimal points which is what you are getting.

You will never get it exact when you are up to eight decimal points because of the vagaries of floating point binary arithmetic. Small errors will always creep in and .00000052 is a very small error. A little over five millionth.

Stuart


0

Response Number 9
Name: cool_andy
Date: December 12, 2007 at 09:28:10 Pacific
Reply:

I think I understand the problem, I suspect this is because the way floating point numbers are handled in binary arithemtic as you mention above. I noticed the webpages Klint posted above "What every computer scientist should know about floating-point arithmetic". Those articles look pretty complicated and difficult to understand.

However I do have one query following klint's last reply.
printf("%12.8f", 11.5549999 + 0.005);
It prints - 11.554999990, correctly

But if a variable is used after adding:
valye = 11.5549999;
value += 0.005;
printf("%12.8f",value);
It prints 11.56000042

I presume that is the way printf is handling the floating point figure?


0

Response Number 10
Name: klint
Date: December 13, 2007 at 02:28:06 Pacific
Reply:

cool_andy,

>But if a variable is used after adding:
>valye = 11.5549999;
>value += 0.005;
>printf("%12.8f",value);
>It prints 11.56000042
>
>I presume that is the way printf is
>handling the floating point figure?

No, this seems to be losing some accuracy. Are you using float? That doesn't hold that many decimal places, try using double. These days, with processors' built-in ability to do 80-bit floating point arithmetic, there is not much point in using float, unless you have a huge array of them and you want to use less memory.


0

Response Number 11
Name: cool_andy
Date: December 13, 2007 at 08:02:11 Pacific
Reply:

Hi,
If I declare "value" as a double variable, I get the following (8.d.p):
11.56000031

Slightly less error margin than using a float figure.
It seems if any figure is over 6.d.p close to the half way point, very small errors always occur.
Despite this I am happy with the useful advice you have given me about rounding floating point figures.
Thanks for your time.

Andrew


0

Response Number 12
Name: klint
Date: December 13, 2007 at 08:34:12 Pacific
Reply:

Strange. Something's just not right.

Using Visual Studio 2003, when I run the following program (copy&paste exact verbatim copy):

#include <stdio.h>

int main()
{
double value = 11.5549999;
value += 0.005;
printf("%12.8f", value);
return 0;
}

... it prints 11.55999990, just as expected. Can you copy & paste your complete application and tell me what it prints, and I'll try with my compiler to see if there is a difference.


0

Response Number 13
Name: cool_andy
Date: December 13, 2007 at 09:25:48 Pacific
Reply:

Ok I have managed to solve the problem. I made a silly mistake by forgeting to change the actually declared variable which was still float. This float variable "value" was being passed into round_double(double value) function, thus still giving an error margin.

I have also discovered the string method I created, is still rounding to 11.56 incorrectly.
But the method you mentioned above returns 11.55 correctly from 11.55999990
(f + 0.005) - fmod(f + 0.005, 0.01)

fmod gets the remainder after 2.d.p, which is 0.0099999.
Therefore 11.5599990 - 0.0099999 = 11.55

That seems to have done trick, thank you very much. Mission accomplished :)
I just have to remember to use double variables instead of float especially when my program contains a lot of discounts and nett prices stored in a linked list.


0

Response Number 14
Name: cool_andy
Date: December 13, 2007 at 09:32:50 Pacific
Reply:

I have just realised my string method does work if I alter sprintf to specify 8.d.p:
sprintf(roundtest,"%.8f",value);

"%lf" is only limiting to 6.d.p


0

Response Number 15
Name: klint
Date: December 13, 2007 at 09:36:40 Pacific
Reply:

If you are working with currency amounts, you may be better off using long int to represent cents (or pence, or whatever your minor unit is.) Integral types have exact representations, rather than being subject to the pitfalls of floating-point.


0

Sponsored Link
Ads by Google
Reply to Message Icon






Post Locked

This post is quite old and has been locked from receiving new replies. Please create a new posting instead.


Go to Programming Forum Home


Sponsored links

Ads by Google


Results for: Slight inaccuracy Rounding Problem

computing large numbers. powers of www.computing.net/answers/programming/computing-large-numbers-powers-of/14731.html

Help with problem in C www.computing.net/answers/programming/help-with-problem-in-c/5108.html

c var precision problem (equations) www.computing.net/answers/programming/c-var-precision-problem-equations/12303.html