Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

In the below example app I calculate the floating point remainder from dividing 953 by 0.1, using std::fmod

What I was expecting is that since 953.0 / 0.1 == 9530, that std::fmod(953, 0.1) == 0

I'm getting 0.1 - why is this the case?

Note that with std::remainder I get the correct result.

That is:

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

Difference between the two functions:

According to cppreference.com

  • std::fmod calculates the following:

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

  • std::remainder calculates the following:

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

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

Exemplar app:

#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
like image 777
Steve Lorimer Avatar asked Oct 22 '14 23:10

Steve Lorimer


People also ask

What does Fmod return in C++?

The fmod() function returns the floating-point remainder of x/y. If y is zero or if x/y causes an overflow, fmod() returns 0.

What does fmod return?

fmod returns the floating-point remainder of x / y . If the value of y is 0.0, fmod returns a quiet NaN . For information about representation of a quiet NaN by the printf family, see printf .

How do you get the remainder of a double in C++?

Syntax : double remainder(double a, double b) float remainder(float a, float b) long double remainder(long double a, long double b) Parameter: a and b are the values of numerator and denominator. Return: The remainder() function returns the floating point remainder of numerator/denominator rounded to nearest.


1 Answers

Because they are different functions.

std::remainder(x, y) calculates IEEE remainder which is x - (round(x/y)*y) where round is rounding half to even (so in particular round(1.0/2.0) == 0)

std::fmod(x, y) calculates x - trunc(x/y)*y. When you divide 953 by 0.1 you may get a number slightly smaller than 9530, so truncation gives 9529. So as the result you get 953.0 - 952.9 = 0.1

like image 110
Anton Savin Avatar answered Nov 09 '22 01:11

Anton Savin