66120

Best practices for floating-point arithmetics

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?

Answer1:

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.

Answer2:

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.

Answer3:

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.

Answer4:

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

Recommend

  • Issue with “na” in arranging the bars in a bar plot in R and ggplot2
  • How to apply filter on comma separated values in oracle?
  • XML Serialization assembly for non-web projects
  • refreshing a WPF window on demand
  • Avoiding try/catch hell in my web pages
  • Default CUDA addition rounding mode between cuda 5.0 and 7.5
  • add two double given wrong result
  • Replicating and differentiating portions of a form
  • Implementing HMAC-SHA256 for Keybase in Javascript
  • SQL Server 2008 R2 - Islands and Gaps [closed]
  • SQL Server: +(unary) operator on non-numeric Strings
  • Jooq casting String to BigDecimal
  • why 0.1+0.2-0.3= 5.5511151231258E-17 in php [duplicate]
  • Can't connect Entity Framework to local SQL Server Express
  • Sympy: working with equalities manually
  • R h2o.glm - issue with max_active_predictors
  • RavenDB indexing errors
  • Multiple Left Join LINQ-to-entities
  • Efficient & Pythonic way of finding all possible sublists of a list in given range and the minim
  • Avoid registering duplicate broadcast receivers in Android
  • Efficient User-Agent Regex to find Safari in Python
  • IE6 changes DOCTYPE to a bad one
  • Is it possible to get the word under the mouse cursor in a ``?
  • Recording values of radio buttons in ember
  • Suqueries in select clause with JPA
  • Python cosine function precision [duplicate]
  • Doctrine/Symfony entity generator and generating entity from one table
  • How to handle elastic beanstalk deployment so it uploads only changed files
  • Check all values in string[] for length?
  • Default parameter as generic type
  • Unable to install Git-core+svn by MacPorts
  • Django simple Captcha “No module named fields” error
  • Could not find rake using whenever rails
  • If I include Java 8 in my Android app does that affect which devices it will work on?
  • Join two tables and save into third-sql
  • How to model a transition system with SPIN
  • ORA-29908: missing primary invocation for ancillary operator
  • Matrix multiplication with MKL
  • Can Visual Studio XAML designer handle font family names with spaces as a resource?
  • Converting MP3 duration time