Why am I getting a different result from std :: fmod and std :: remainder

In the example below, the application calculates the remainder of the floating point from dividing 953 by 0.1 using std::fmod

I expected with 953.0 / 0.1 == 9530 that std::fmod(953, 0.1) == 0

I get 0.1 - why is this so?

Please note that with std::remainder I get the correct result.

I.e:

 std::fmod (953, 0.1) == 0.1 // unexpected std::remainder(953, 0.1) == 0 // expected 

The difference between the two functions:

According to cppreference.com

  • std::fmod computes the following:

exactly the value x - n*y , where n - x/y , and its fractional part is truncated

  • std::remainder computes the following:

exactly the value x - n*y , where n is the integral value, the nearest exact value x/y

Given my inputs, I would expect both functions to have the same output. Why is this not so?

Exemplar example:

 #include <iostream> #include <cmath> bool is_zero(double in) { return std::fabs(in) < 0.0000001; } int main() { double numerator = 953; double denominator = 0.1; double quotient = numerator / denominator; double fmod = std::fmod (numerator, denominator); double rem = std::remainder(numerator, denominator); if (is_zero(fmod)) fmod = 0; if (is_zero(rem)) rem = 0; std::cout << "quotient: " << quotient << ", fmod: " << fmod << ", rem: " << rem << std::endl; return 0; } 

Output:

 quotient: 9530, fmod: 0.1, rem: 0 
+2
source share
2 answers

Welcome to floating point math. Here's what happens: one tenth cannot be represented exactly in binary form, just as one third cannot be represented exactly in decimal form. As a result, the unit gives the result just below 9530. The operation on the floor gives the integer 9529 instead of 9530. And then this leaves 0.1 on the left.

+9
source

Because these are different functions.

std::remainder(x, y) calculates the IEEE remainder , which is x - (round(x/y)*y) .

std::fmod(x, y) computes x - trunc(x/y)*y . When you divide 953 by 0.1 , you can get a number slightly smaller than 9530, so truncating gives 9529. Thus, you get 953.0 - 952.9 = 0.1

+8
source

All Articles