增量浮点数彼此不相等[重复]

时间:2021-12-02 11:29:26

Possible Duplicate:
Why can't decimal numbers be represented exactly in binary?
Program not entering if statement

可能重复:为什么十进制数不能完全用二进制表示?程序不输入if语句

So I'm trying to run a program that has two variables, when one variable is equal to another, it performs a function. In this case, printing spam. However, for some reason, when I run this program, I'm not getting any output even though I know they are equal.

所以我试图运行一个有两个变量的程序,当一个变量等于另一个变量时,它会执行一个函数。在这种情况下,打印垃圾邮件。但是,出于某种原因,当我运行这个程序时,即使我知道它们是相同的,我也没有得到任何输出。

g=0.0
b=3.0

while g < 30.0:
    if g==b:
        print "Hi"
    g+=.1
    print g, b

3 个解决方案

#1


9  

You are assuming that adding .1 enough times to 0.0 will produce 3.0. These are floating point numbers, they are inaccurate. Rounding errors make it so that the value is never exactly equal to 3.0. You should almost never use == to test floating point numbers.

您假设将.1足够的时间添加到0.0将产生3.0。这些是浮点数,它们是不准确的。舍入错误使得该值永远不会完全等于3.0。您几乎不应该使用==来测试浮点数。

#2


6  

A good way to do this is to count with integer values (e.g., loop with i from 0 to 300 by 1) and scale the counter only when the float value is used (e.g., set f = i * .1). When you do this, the loop counter is always exact, so you get exactly the iterations you want, and there is only one floating-point rounding, which does not accumulate from iteration to iteration.

执行此操作的一种好方法是使用整数值(例如,将i从0到300的循环除以1)进行计数,并仅在使用浮点值时缩放计数器(例如,设置f = i * .1)。当你这样做时,循环计数器总是精确的,所以你得到你想要的精确迭代,并且只有一个浮点舍入,它不会从迭代到迭代累积。

The loop counter is most commonly an integer type, so that addition is easily seen to be exact (until overflow is reached). However, the loop counter may also be a floating-point type, provided you are sure that the values and operations for it are exact. (The common 32-bit floating-point format represents integers exactly from -224 to +224. Outside that, it does not have the precision to represent integers exactly. It does not represent .1 exactly, so you cannot count with increments of .1. But you could count with increments of .5, .25, .375, or other small multiples of moderate powers of two, which are represented exactly.)

循环计数器通常是整数类型,因此很容易看出加法是准确的(直到达到溢出)。但是,循环计数器也可以是浮点类型,前提是您确定它的值和操作是精确的。 (常见的32位浮点格式表示从-224到+224的整数。除此之外,它没有准确表示整数的精度。它并不完全代表.1所以你不能用增量来计算。但是你可以用.5,.25,.375的增量或其他两个中等幂的倍数来计算。

#3


0  

To expand on Karoly Horvath's comment, what you can do to test near-equality is choose some value (let's call it epsilon) that is very, very small relative to the minimum increment. Let's say epsilon is 1.0 * 10^-6, five orders of magnitude smaller than your increment. (It should probably be based on the average rounding error of your floating point representation, but that varies, and this is simply an example).

为了扩展Karoly Horvath的评论,你可以做些什么来测试近似相等是选择一个相对于最小增量非常非常小的值(让我们称之为epsilon)。假设epsilon是1.0 * 10 ^ -6,比你的增量小五个数量级。 (它可能应该基于浮点表示的平均舍入误差,但这会有所不同,这只是一个例子)。

What you then do is check if g and b are less than epsilon different - if they are close enough that they are practically equal, the difference between practically and actually being the rounding error, which you're approximating with epsilon.

你接下来要做的是检查g和b是否小于epsilon不同 - 如果它们足够接近它们实际上是相等的,实际上和实际上是舍入误差之间的差异,你用epsilon逼近。

Check for

abs(g - b) < epsilon

and you'll have your almost-but-not-quite equality check, which should be good enough for most purposes.

并且你将进行几乎但不完全相等的检查,这对于大多数用途来说应该足够好。

#1


9  

You are assuming that adding .1 enough times to 0.0 will produce 3.0. These are floating point numbers, they are inaccurate. Rounding errors make it so that the value is never exactly equal to 3.0. You should almost never use == to test floating point numbers.

您假设将.1足够的时间添加到0.0将产生3.0。这些是浮点数,它们是不准确的。舍入错误使得该值永远不会完全等于3.0。您几乎不应该使用==来测试浮点数。

#2


6  

A good way to do this is to count with integer values (e.g., loop with i from 0 to 300 by 1) and scale the counter only when the float value is used (e.g., set f = i * .1). When you do this, the loop counter is always exact, so you get exactly the iterations you want, and there is only one floating-point rounding, which does not accumulate from iteration to iteration.

执行此操作的一种好方法是使用整数值(例如,将i从0到300的循环除以1)进行计数,并仅在使用浮点值时缩放计数器(例如,设置f = i * .1)。当你这样做时,循环计数器总是精确的,所以你得到你想要的精确迭代,并且只有一个浮点舍入,它不会从迭代到迭代累积。

The loop counter is most commonly an integer type, so that addition is easily seen to be exact (until overflow is reached). However, the loop counter may also be a floating-point type, provided you are sure that the values and operations for it are exact. (The common 32-bit floating-point format represents integers exactly from -224 to +224. Outside that, it does not have the precision to represent integers exactly. It does not represent .1 exactly, so you cannot count with increments of .1. But you could count with increments of .5, .25, .375, or other small multiples of moderate powers of two, which are represented exactly.)

循环计数器通常是整数类型,因此很容易看出加法是准确的(直到达到溢出)。但是,循环计数器也可以是浮点类型,前提是您确定它的值和操作是精确的。 (常见的32位浮点格式表示从-224到+224的整数。除此之外,它没有准确表示整数的精度。它并不完全代表.1所以你不能用增量来计算。但是你可以用.5,.25,.375的增量或其他两个中等幂的倍数来计算。

#3


0  

To expand on Karoly Horvath's comment, what you can do to test near-equality is choose some value (let's call it epsilon) that is very, very small relative to the minimum increment. Let's say epsilon is 1.0 * 10^-6, five orders of magnitude smaller than your increment. (It should probably be based on the average rounding error of your floating point representation, but that varies, and this is simply an example).

为了扩展Karoly Horvath的评论,你可以做些什么来测试近似相等是选择一个相对于最小增量非常非常小的值(让我们称之为epsilon)。假设epsilon是1.0 * 10 ^ -6,比你的增量小五个数量级。 (它可能应该基于浮点表示的平均舍入误差,但这会有所不同,这只是一个例子)。

What you then do is check if g and b are less than epsilon different - if they are close enough that they are practically equal, the difference between practically and actually being the rounding error, which you're approximating with epsilon.

你接下来要做的是检查g和b是否小于epsilon不同 - 如果它们足够接近它们实际上是相等的,实际上和实际上是舍入误差之间的差异,你用epsilon逼近。

Check for

abs(g - b) < epsilon

and you'll have your almost-but-not-quite equality check, which should be good enough for most purposes.

并且你将进行几乎但不完全相等的检查,这对于大多数用途来说应该足够好。