c# modulus operator on floats

c# modulus operator on floats

下面的代码对数字 0.01、0.02、0.03、...、0.99 运行模数 0.01

var testVals = Enumerable.Range(1, 99).Select(n => double.Parse("0." + n.ToString("D2")));
var moduloTest = testVals.Select(v => v % 0.01).ToList();

(注意:从字符串中解析双精度数是有意的,这样对浮点数进行的唯一数学运算就是模数)

我希望此处的 moduleTest 列表包含几个非常接近 0 的浮点值。但是列表中的许多值反而非常接近 0.1。

我知道浮点数学并不精确,会引入舍入误差,但这里的 0.1 甚至不接近 0。

我在打字时意识到了答案。它确实是由于浮点数的不精确而发生的。只是对于模数运算,与大多数数学运算不同,值的微小不精确可能会导致结果出现很大差异。

例如,0.03 在浮点数中最接近表示为 0.2999999999999999999,如果您要对 0.01 取模,则会得到一个类似 0.0999999999999

的数字

I understand that floating point math is not exact, but in many cases here it seems to be not even close.

这里的模数没有加上error/inexactness,只是让先验不精确的影响非常明显。


通过高质量的模数实现,没有不精确之处。参见 Is fmod() exact when y is an integer?

问题在于假设具有小数值(如 0.01)的数学总是表现接近那些转换为最接近的可表示浮点数的值。有限浮点值都是精确的。形成它们的值的操作是“错误”出现的地方——除了模数等一些例外。

以十六进制或足够的十进制精度(例如 17 有效 小数位)打印值通常足以显示预期的 0.01 未编码为浮点数 0.01,而是一个值 near 那。对计算结果也执行此操作以获得更深入的了解。

模运算的本质是sawtooth curve like the green line here

鉴于在 0.01 转换和 / 中产生的误差,(不是模数),OP 值的模数结果 预期 就在不连续性:大约 0.0 或接近 0.01。