Best practices for floating-point arithmetics

邮差的信 提交于 2019-12-12 22:10:05

问题


I was performing addition and subtraction on an input of decimals that are precise to the second decimal place. I tried to improve accuracy by converting them to integers through multiplying 100, but achieved opposite effects.

Consider the following code and output:

double d = 2.01;
int a = (int) (d * 100.0);
cout << a << endl;

The output is:

200

Once and for all, what are some of the best practices regarding floating-point arithmetics? Is it at all feasible to first convert the double to an int using some variant of the code above, and then casting it back?


回答1:


If you print out the result of d*100.0 to (say) 20 decimal places, the problem will quickly become apparent:

200.99999999999997

Since that's (ever so minutely) less than 201, it gets truncated to 200 when you cast to int.

The obvious cure is to force rounding. At least if your inputs are all positive that can be as simple as adding 0.5 to the result:

int a = (int)(d*100.0 + 0.5);

If you can count on your compiler supporting it, it's even easier to use the standard library's round:

long a = lround(d*100.0);

This works correctly for both positive and negative numbers.




回答2:


Use the standard math library's rounding functions. In C++ this means you will have to #include <cmath> and compile with -lm.

Then, for your example:

double d = 2.01;
long x = lround(d*100);
cout << x << endl; // prints 201, for sure.

This will be the same as the "add .5" trick, but it will work correctly for positive and negative numbers.




回答3:


Read this and reach enlightenment:

What Every Computer Scientist Should Know About Floating-Point Arithmetic

Floating-point arithmetic is considered an esoteric subject by many people. This is rather surprising because floating-point is ubiquitous in computer systems. Almost every language has a floating-point datatype; computers from PCs to supercomputers have floating-point accelerators; most compilers will be called upon to compile floating-point algorithms from time to time; and virtually every operating system must respond to floating-point exceptions such as overflow. This paper presents a tutorial on those aspects of floating-point that have a direct impact on designers of computer systems. It begins with background on floating-point representation and rounding error, continues with a discussion of the IEEE floating-point standard, and concludes with numerous examples of how computer builders can better support floating-point.




回答4:


In order to get well defined rouding, I would use floor() and ceil().

So, for the following code,

 (int)floor( 2.01*100.)

I get:

200

But for:

(int)ceil(2.01*100.)

I get:

201


来源:https://stackoverflow.com/questions/24665459/best-practices-for-floating-point-arithmetics

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!