7

The .net framework includes Math.IEEERemainder(x, y) in addition to the standard mod operator. What is this function really doing? I dont understand the negative numbers that this produces.

Example:

Math.IEEERemainder(0, 2) = 0
Math.IEEERemainder(1, 2) = 1
Math.IEEERemainder(2, 2) = 0
Math.IEEERemainder(3, 2) = -1
Jeffrey
  • 1,837
  • 5
  • 25
  • 40

1 Answers1

8

If you read the example given at System.Math.IEEERemainder's MSDN page, you'll notice that two positive numbers can have a negative remainder.

Return Value

A number equal to x - (y Q), where Q is the quotient of x / y rounded to the nearest integer (if x / y falls halfway between two integers, the even integer is returned).

So: 3 - (2 * (round(3 / 2))) = -1

/*
...
Divide two double-precision floating-point values:
1) The IEEE remainder of 1.797693e+308/2.00 is 0.000000e+000
2) The IEEE remainder of 1.797693e+308/3.00 is -1.000000e+000
Note that two positive numbers can yield a negative remainder.

*/

Epilogue

The actual question could be, "Why do we have two remainder operations?" When dealing with floating point data, you always need to be cognizant of your floating point standard. Since we're in the 21st century, most everything is on IEEE 754 and very few of us worry about say VAX F_Float versus IEEE 754.

The C# standard states that the remainder operator (Section 7.7.3), when applied to floating point arguments, is analogous to the remainder operator when applied to integer arguments. That is, the same mathematical formula1 is used (with additional considerations for corner cases associated with floating point representations) in both integer and floating point remainder operations.

Therefore, if you are looking to have your remainder operations on floating point numbers conform to your current IEEE 754 rounding modes, it is advisable to use Math.IEEERemainder. However, if your usage is not particularly sensitive to the subtle difference in rounding produced by the C# remainder operator, then continue using the operator.

  1. Given: z = x % y, then z = x - (x / y) * y
Community
  • 1
  • 1
user7116
  • 63,008
  • 17
  • 141
  • 172
  • That's exactly what I was just about to post. Get out of my head. ;) – Jeff Yates Oct 01 '08 at 15:20
  • 1
    @ffpf: haha, well an interesting post would be why you have/need Modulo and IEEERemainder. You can beat me to adding that if you'd like :D – user7116 Oct 01 '08 at 15:22
  • @sixlettervariables: No, I'm not asking. I'm scared of the answer. – Jeff Yates Oct 01 '08 at 15:28
  • @ffpf: enjoy the answer, it isn't earth shattering. – user7116 Oct 01 '08 at 15:31
  • 2
    The IEEE 754 rounding modes have no bearing on either the `IEEERemainder` operation or the `%` operation because both are exact. Being exact means that the result is the same regardless of the rounding mode. What differs between them is the underlying notion of integral quotient. `IEEERemainder` rounds the mathematical quotient to the nearest integer to get the `q` in `x - q * y`. – Pascal Cuoq Jan 13 '16 at 14:38
  • 1
    You say "most everything is on IEEE 754", but I don't see how that's relevant since the question is why C# (and most other languages) explicitly do NOT implement IEEE 754 for the modulus operator. – BlueRaja - Danny Pflughoeft Jun 07 '17 at 16:48