0

I read here that remquo should return:

If successful, returns the floating-point remainder of the division x/y as defined in std::remainder, and a value whose sign is the sign of x/y and whose magnitude is congruent modulo 2n to the magnitude of the integral quotient of x/y, where n is an implementation-defined integer greater than or equal to 3.

Now clearly I've misunderstood all that techno-speak cause I thought that I was going to get back the fractional result of the division. Instead this operation:

int quot;
const float rem = remquo(7.0F, 4.0F, &quot);

Sets quot to 2 and rem to -1.0! I can see how that is valid because 4.0 * 2 = 8.0 and 7.0 - 8.0 = -1.0. But why are we using a quot that will result in a negative rem? Shouldn't I be getting back a quot of 1 and a rem of 3.0?

Jonathan Mee
  • 37,899
  • 23
  • 129
  • 288
  • Are you talking about C or C++? They are different languages. – too honest for this site Jan 13 '16 at 13:21
  • @Olaf This is a C function I'm asking about and is implemented the same in both languages. If you can explain it to me in C you've explained it to me in C++. Alternatively if you can explain it to me in C++ you're explained it to me in C. – Jonathan Mee Jan 13 '16 at 13:24
  • You are not citing the C standard, but the C++ standard. – too honest for this site Jan 13 '16 at 13:25
  • @Olaf It's the same as the C documentation: http://en.cppreference.com/w/c/numeric/math/remquo – Jonathan Mee Jan 13 '16 at 13:27
  • @JonathanMee Possibly related: http://stackoverflow.com/questions/11630321/why-does-c-output-negative-numbers-when-using-modulo – πάντα ῥεῖ Jan 13 '16 at 13:32
  • It is not and clearly cannot be, because there is no `std::` in C. However, it is congruent. But note that cppreference is no authoritative ressource. As far as I understand, for `r = remquo(x, y, &q)` it should be `x == q * y + r`. That is the same as for the remainder in general. It just seems `q` is somehow modulo `pow(2, n)` (I'm not sure about that part in the spec). It might become more surprisingly with larger `x` and/or non-power of two values. – too honest for this site Jan 13 '16 at 13:36
  • @Olaf The spec cannot say that `*quot` receives the integral quotient because the integral quotient of two `float`s does not in general fit in an `int`. Instead, only the low bits of the integral quotient are provided. The spec is just saying that at least 3 of the least significant bits will be shown, in an unclear manner. – Pascal Cuoq Jan 13 '16 at 14:11
  • @PascalCuoq: I had not problems about the "integral" part, but the modulo. While understood what it does, the reason was not clear to me. A short footnote would have been very welcome. But maybe one has to know IEC 60559 to understand this fully. – too honest for this site Jan 13 '16 at 14:14

2 Answers2

1

Since your question is about the value returned by remquo, it is entirely about std::remainder, since that part of remquo's behavior is defined directly as identical to that of std::remainder.

std::remainder provides the IEEE 754 remainder operation, which is different from fmod in that the fmod of two positive values can be expected to be always positive, whereas the IEEE 754 remainder is defined with respect to the integral quotient q as the nearest integer to the mathematical quotient x/y, so that remainder = x - y*q produces a negative result each time the mathematical quotient rounds up to the next integer.

The IEEE 754 remainder operation is the one being discussed in the question “Math.IEEERemainder returns negative results.” so you might want to read it and the accepted answer although they are about a different programming language.

Note: the part of the specification about the quotient being “congruent modulo 2n to the magnitude of the integral quotient” simply means that you do not get the entire integral quotient, which indeed might not fit an int type (think of remquo(FLT_MAX, 1.0f, ...). Instead, you get an implementation-defined number of the least significant bits of the integral quotient. The implementation-defined number of bits that you get must be at least three, but can be more.

Community
  • 1
  • 1
Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
  • 1
    Thanks for clarification about that "congruent" part. The standards (C and C++) really could have been more clear about that it is just to fit the value into an integer. I just wonder why they just use three bits, because an `int` has at least 15 magnitude bits. – too honest for this site Jan 13 '16 at 14:10
  • @Olaf The sort of people who would use `remquo` often only care about the last few bits of the integral quotient. Consider `remquo(…, M_PI_2, …)` (and that's a bit of a bad example because you might really be more interested in the remainder in the division by the real π, not the floating-point approximation of it, but bear with me): you might want to know if the integer quotient is even or odd, perhaps if it's congruent to 0, 1, 2 or 3 modulo 4, but not care so much about the higher-order bits. – Pascal Cuoq Jan 13 '16 at 14:19
  • Thanks for explaining. I actually try to avoid floating point when possible (and until now, I was lucky in my C projects;-) – too honest for this site Jan 13 '16 at 14:21
  • @PascalCuoq: I just encountered the same behavior as OP, which surprised me because [the documentation for the function I called](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/remquo-remquof-remquol?view=msvc-150) claims that "The remquo function calculates the floating-point remainder f of x / y such that x = i * y + f, where i is an integer, **f has the same sign as x**, and the absolute value of f is less than the absolute value of y." Can you confirm that claim in the manpage is pure baloney? – Ben Voigt Jul 05 '22 at 20:38
  • @BenVoigt This documentation is problematic in at least two ways: the one you found, and the fact that it says “approximate magnitude of the quotient” which is a terrible way of stating that the three **lowest-order** bits of the quotient are the only ones that are guaranteed correct (“magnitude” implies that the highest-order bits of the quotient are the ones that can be relied on). – Pascal Cuoq Jul 20 '22 at 19:06
1

The behavior is correct; as stated in std::remainder, the quotient is rounded to nearest integer, then the remainder could be negative.

If you are working with integer, I suggest you the C function div()