Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

fmod or not fmod?

Tags:

c++

c

math

I dug into old code, and saw a function like this:

inline double mod(double x, double y)
{
    return x-y*floor(x/y);
}

is fmod its full equivalent, or have I missed something?

like image 491
user1244932 Avatar asked Nov 10 '15 14:11

user1244932


1 Answers

No, the above routine it is not the same as fmod(). Specifically it is different for situations where one argument is negative.

Your routine does a floor(), which rounds down to the next integer. With fmod() the rounding is like trunc(), i.e. towards zero.

Here's an extract from the Open Group standard (here):

These functions shall return the value x- i* y, for some integer i such that, if y is non-zero, the result has the same sign as x and magnitude less than the magnitude of y.

If the correct value would cause underflow, and is not representable, a range error may occur, and either 0.0 (if supported), or an implementation-defined value shall be returned.

If x or y is NaN, a NaN shall be returned

If y is zero, a domain error shall occur, and either a NaN (if supported), or an implementation-defined value shall be returned.

If x is infinite, a domain error shall occur, and either a NaN (if supported), or an implementation-defined value shall be returned.

If x is ±0 and y is not zero, ±0 shall be returned.

If x is not infinite and y is±Inf, x shall be returned.

If the correct value would cause underflow, and is representable, a range error may occur and the correct value shall be returned.

That's difficult to understand, but the word 'magnitude' in the first paragraph illustrates the rounding is towards zero.

Here's an extract from the much more helpful documentation for the GCC library:

These functions compute the remainder from the division of numerator by denominator. Specifically, the return value is numerator - n * denominator, where n is the quotient of numerator divided by denominator, rounded towards zero to an integer. Thus, fmod (6.5, 2.3) returns 1.9, which is 6.5 minus 4.6.

like image 65
abligh Avatar answered Sep 25 '22 18:09

abligh