【发布时间】:2008-10-01 23:31:29
【问题描述】:
.net 框架除了标准的 mod 运算符外,还包括 Math.IEEERemainder(x, y)。这个函数到底在做什么?我不明白这会产生负数。
例子:
Math.IEEERemainder(0, 2) = 0
Math.IEEERemainder(1, 2) = 1
Math.IEEERemainder(2, 2) = 0
Math.IEEERemainder(3, 2) = -1
【问题讨论】:
.net 框架除了标准的 mod 运算符外,还包括 Math.IEEERemainder(x, y)。这个函数到底在做什么?我不明白这会产生负数。
例子:
Math.IEEERemainder(0, 2) = 0
Math.IEEERemainder(1, 2) = 1
Math.IEEERemainder(2, 2) = 0
Math.IEEERemainder(3, 2) = -1
【问题讨论】:
如果您阅读System.Math.IEEERemainder's MSDN page 给出的示例,您会注意到两个正数的余数可能为负。
返回值
一个等于 x - (y Q) 的数,其中 Q 是 x / 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# standard 指出,当应用于浮点参数时,余数运算符(第 7.7.3 节)类似于应用于整数参数时的余数运算符。也就是说,整数和浮点余数运算都使用相同的数学公式1(另外考虑与浮点表示相关的极端情况)。
因此,如果您希望浮点数的余数运算符合您当前的 IEEE 754 舍入模式,建议使用 Math.IEEERemainder。但是,如果您的用法对 C# 余数运算符产生的舍入的细微差别不是特别敏感,那么请继续使用该运算符。
【讨论】:
IEEERemainder 操作或% 操作无关,因为两者都是精确的。精确意味着无论舍入模式如何,结果都是相同的。它们之间的不同之处在于积分商的基本概念。 IEEERemainder 将数学商四舍五入到最接近的整数,得到x - q * y 中的q。