Math.IEEERemainder返回负数结果。为什么?

7

除了标准的取模运算符,.net框架还包括Math.IEEERemainder(x,y)函数。这个函数到底是在做什么?我不理解它产生的负数。

例子:

Math.IEEERemainder(0, 2) = 0
Math.IEEERemainder(1, 2) = 1
Math.IEEERemainder(2, 2) = 0
Math.IEEERemainder(3, 2) = -1
1个回答

8
如果您阅读 System.Math.IEEERemainder 的 MSDN 页面 上的示例,您将注意到两个正数可以有一个负余数。 返回值 一个等于 x - (y Q) 的数字,其中 Qx / y 的商四舍五入到最近的整数(如果 x / y 介于两个整数之间,则返回偶数整数)。
所以: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.

*/

结语

实际问题可能是,“为什么我们有两个余数运算?”在处理浮点数据时,你总是需要注意你的浮点标准。由于我们处于21世纪,大多数东西都是基于IEEE 754的,很少有人关心VAX F_Float与IEEE 754之间的差异。

C#标准指出,当对浮点参数应用余数运算符(第7.7.3节)时,它类似于当对整数参数应用余数运算符。也就是说,在整数和浮点余数操作中使用相同的数学公式1(针对与浮点表示相关的边角情况的额外考虑),因此,如果您希望将浮点数的余数运算符符合当前的IEEE 754舍入模式,则建议使用Math.IEEERemainder。但是,如果你的使用不特别敏感于C#余数运算符产生的微妙舍入差异,那么继续使用这个运算符即可。

  1. 给定:z = x%y,则z = x -(x / y)* y

这正是我刚想要发布的。走出我的脑海。;) - Jeff Yates
1
@ffpf:哈哈,一个有趣的帖子是为什么你需要模数和IEEERemainder。如果你愿意,你可以先加上去:D - user7116
@sixlettervariables:不,我不是在问。我害怕得到答案。 - Jeff Yates
@ffpf:享受这个答案,它并不是惊天动地的。 - user7116
2
IEEE 754的舍入模式对IEEERemainder操作或%操作没有影响,因为两者都是精确的。精确意味着结果不受舍入模式的影响。它们之间的区别在于整数商的基本概念。IEEERemainder将数学商四舍五入到最近的整数以得到x - q * y中的q - Pascal Cuoq
1
你说“大多数东西都在IEEE 754上”,但我不明白这与问题有什么关系,因为问题是为什么C#(以及大多数其他语言)明确地没有实现IEEE 754作为模运算符。 - BlueRaja - Danny Pflughoeft

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接