Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rounding differences on Windows vs Unix based system in sprintf

I have problem on UNIX based systems sprintf does not round up properly value.

For example

double tmp = 88888888888885.875
char out[512];

Thats 88,888,888,888,885.875 just to be easier on eyes. I am giving such specific and big example because it seems it works fine on smaller numbers.

I am trying to use it in following way

sprintf(out, "%021.2f", tmp);
printf("out = %s\n", tmp);

On windows this results in:

out = 000088888888888885.88

On for example AIX, but shows in Linux as well:

out = 000088888888888885.87

Why is this happening? Any ideas and how to make it behave same way on Win/Unix

Thanks

like image 705
grobartn Avatar asked Jan 10 '11 17:01

grobartn


2 Answers

There is a bug report for glibc with a problem very similar to yours. The main conclusion (in comment 46) here is that double is not a 15-decimal-digit number and you should not expect it to work like that.

As a workaround you can add something small to your numbers to make them round better. But this solution is not general because it depends on number ranges you deal with.

Another workaround can be multiplying to prepare them for rounding, then rounding (e.g. 2597.625*100 = 259762.5 -> 259763 = 2597.63*100)

However I think there must be smarter workarounds.

like image 160
ssmir Avatar answered Nov 06 '22 23:11

ssmir


What floating point representations are used by your processor and your compiler?

Not all processors use the same way to represent floating-point values and even compilers may choose different floating-point representation methods (I think the Microsoft C++ compiler even has options to choose the representation).

The page http://www.quadibloc.com/comp/cp0201.htm gives an overview of some of the floating-point representations (although they seem to be rather old architectures shown there).

http://msdn.microsoft.com/en-us/library/0b34tf65.aspx describes how Microsoft Visual C++ stores floating-point values. I couldn't find immediately what representation is used by AIX or Linux.

Additinally, every compiler has options that let you indicate how you want to work with floating-point operations. Do you want them to be correct as possible (but possibly somewhat slower)? Or do you want floating-point operations to be fast as possible (but possibly less correct)?

like image 33
Patrick Avatar answered Nov 06 '22 23:11

Patrick