双型模运算符 - 浮点运算 [英] Floating Point Arithmetic - Modulo Operator on Double Type

查看:106
本文介绍了双型模运算符 - 浮点运算的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

所以我想找出为什么模运算符是返回如此大的不同寻常的价值。

So I'm trying to figure out why the modulo operator is returning such a large unusual value.

如果我有code:

双重结果= 1.0D 0.1D%;

这会给的结果0.09999999999999995 。我希望 0

请注意这个问题使用的分割操作符不存在 -
双重结果= 1.0D / 0.1D;

Note this problem doesn't exist using the dividing operator - double result = 1.0d / 0.1d;

将给出结果 10.0 ,这意味着其余的的是 0

will give a result of 10.0, meaning that the remainder should be 0.

我要明确指出:我并不感到惊讶,存在一个错误,我很惊讶,错误的是这么混账的相比,在游戏中的数字。 0.0999〜= 0.1和0.1是相同的数量级顺序为 0.1D 和幅度只有一个订单远离 1.0D 。它不喜欢你可以把它比作一个double.epsilon,或者说,它如果相等的< 0.00001差异。

Let me be clear: I'm not surprised that an error exists, I'm surprised that the error is so darn large compared to the numbers at play. 0.0999 ~= 0.1 and 0.1 is on the same order of magnitude as 0.1d and only one order of magnitude away from 1.0d. Its not like you can compare it to a double.epsilon, or say "its equal if its < 0.00001 difference".

我已经在StackOverflow上这个话题读了,在下面的帖子的 之一 2 <一个href=\"http://stackoverflow.com/questions/485175/c-net-is-it-safe-to-check-floating-point-values-for-equality-to-0\">three,在其他人中。

I've read up on this topic on StackOverflow, in the following posts one two three, amongst others.

任何人都可以提出解释为什么这个错误是如此之大?任何任何建议,以避免陷入对未来的问题(我知道我可以使用十进制来代替,但我担心的是,性能)。

Can anyone suggest explain why this error is so large? Any any suggestions to avoid running into the problems in the future (I know I could use decimal instead but I'm concerned about the performance of that).

编辑:我要特别指出的是,我知道0.1是一个无限重复系列二进制数 - 这是否有什么用它做

I should specifically point out that I know that 0.1 is an infinitely repeating series of numbers in binary - does that have anything to do with it?

推荐答案

错误来约,因为双重不能确切地重新present 0.1 - 它可以重新present最接近的是一样的东西0.100000000000000005551115123126。现在,当你通过除以1.0它给你一个数比10略少,但同样的双重不能确切地重新present它,所以它最终舍入到10。但是当你做的MOD,它可以给你的略低于0.1剩余部分。

The error comes about because a double can't exactly represent 0.1 -- the closest it can represent is something like 0.100000000000000005551115123126. Now when you divide 1.0 by that it gives you a number slightly less than 10, but again a double can't exactly represent it, so it ends up rounding up to 10. But when you do the mod, it can give you that slightly less than 0.1 remainder.

由于0 = 0.1 MOD 0.1,在mod的实际误差为0.1 - 0.09999999 ... - 很小

since 0 = 0.1 mod 0.1, the actual error in the mod is 0.1 - 0.09999999... -- very small.

如果您添加%运营商9 * 0.1的结果,它会再次给你1.0。

If you add the result of the % operator to 9 * 0.1, it will give you 1.0 again.

修改

这是四舍五入的东西多一点细节 - 特别是这个问题是混合precision的危险的一个很好的例子。

A bit more detail on the rounding stuff -- particularly as this problem is a good example of the perils of mixed precision.

该方法 A%B 浮点数通常计算是 A - (B *楼(A / B))。问题是,它可以与更多的内部precision一次全部完成比你与这些操作获得(和四舍五入的结果在每个阶段FP数),所以它可能给你一个不同的结果。其中一个例子,很多人看到的是与英特尔的x86 /的x87硬件使用中间计算的80位precision只有64位的内存值precision。因此,在 b的值在上面的等式从内存中来,因此这似乎不太0.1(感谢的确切值dan04)一个64位浮点数字,因此,当它计算1.0 / 0.1它得到9.99999999999999944488848768742172978818416595458984375(四舍五入至80位)。现在,如果你一轮到64位,这将是10.0,但如果保持80位内部做就可以了地板上,将截取9.0,从而得到.0999999999999999500399638918679556809365749359130859375作为最终的答案。

The way a % b for floating point numbers is usually computed is as a - (b * floor(a/b)). The problem is that it may be done all at once with more internal precision than you'd get with those operations (and rounding the result to a fp number at each stage), so it might give you a different result. One example that a lot of people see is with the Intel x86/x87 hardware is using 80-bit precision for intermediate computations and only 64-bit precision for values in memory. So the value in b in the equation above is coming from memory and is thus a 64-bit fp number that's not quite 0.1 (thank dan04 for the exact value), so when it computes 1.0/0.1 it gets 9.99999999999999944488848768742172978818416595458984375 (rounded to 80 bits). Now if you round that to 64 bits, it would be 10.0, but if you keep the 80 bit internal and do the floor on it, it truncates to 9.0 and thus gets .0999999999999999500399638918679556809365749359130859375 as the final answer.

因此​​,在这种情况下,你是因为你使用的是不连续的阶跃函数(地板),这意味着在内部价值一个非常小的差异可以推动你在一步看到一个大的明显错误。但由于mod本身是一个不连续的阶跃函数那可以预期的,这里的真正的错误是0.1-0.0999 ...... 0.1是在MOD功能范围内的不连续点。

So in this case, you're seeing a large apparent error because you're using a noncontinuous step function (floor) which means that a very tiny difference in an internal value can push you over the step. But since mod is itself a noncontinuous step function thats to be expected and the real error here is 0.1-0.0999... as 0.1 is the discontinuous point in the range of the mod function.

这篇关于双型模运算符 - 浮点运算的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆