在我的python程序中,沒有輸入if語句。我已將代碼簡化爲以下內容:程序沒有輸入if語句
x = -5
while x < 5:
if (x == 0):
print 0
x += .01
此程序不輸出任何內容。
但是,將最後一行更改爲x + = .5會使程序輸出0.問題是什麼?
在我的python程序中,沒有輸入if語句。我已將代碼簡化爲以下內容:程序沒有輸入if語句
x = -5
while x < 5:
if (x == 0):
print 0
x += .01
此程序不輸出任何內容。
但是,將最後一行更改爲x + = .5會使程序輸出0.問題是什麼?
浮點數表示可能不夠準確。你不應該測試零相等性,而應該使用一些東西
if (abs(x) < 1E-10) ...
和'abs(x - y)ε'一般來說,其中'x'和'y'是您正在比較的值,而'epsilon'是一個小於您所關心的誤差範圍的小數字。 – delnan
雖然這個修復很煩人。例如,如果我想在零點以外的地方使用,如果我想在.05的話,就必須使用.04999
不幸的是,「修復」是不可能的,因爲「等於」對於不同的人來說可能意味着完全不同的東西。請注意,python的人都知道這一點,並提供解釋:http://docs.python.org/tutorial/floatingpoint.html – drozzy
這是一個四捨五入的問題 - 十進制值不能完全以二進制表示的,所以X從未恰好等於0.0000000000 ....
嘗試if -0.001 < x < 0.001:
BTW更換if (x == 0):
,括號是一個不必要的python if
聲明。
編輯: 打印出來-1和1之間的值在0.01示出了該步驟的話 - 其中零應該是它打印7.52869988574e-16。
_有些十進制值可以用二進制精確表示。 「0.1」不是這些值中的一個。 – agf
@agf:是的,我應該做得更清楚。這就是爲什麼0.5工作,但0.1不工作 - 0.5在二進制中完全可以表示。 –
在二進制中,.01沒有確切的表示,但是.5沒有。
如果你將1/3代表爲.333333,並且一直添加1/3直到達到1,那麼這與你在十進制中遇到的問題是一樣的。三次添加之後,您將擁有.999999,它不完全等於1.
Don't compare non-integers for equality除非你正確理解這樣做的規則,並100%確定你的情況是可以工作的規則之一。
-0.01
7.52869988574e-16
0.01
我建議你說X> -.001和X < 0.001或排序
其他人所指出的問題與浮點數是不能準確地表示值的東西。如果你需要一些確切十進制表示,你可以使用Decimal
類:
from decimal import Decimal
x = Decimal(-5)
while x < 5:
if (x == 0):
print 0
x += Decimal(".01")
這將打印0
如您所願。
注意使用字符串作爲增量。如果您使用的是Decimal(.01)
,則會出現與0.01的精確表示相同的問題,因爲您正在從浮點數轉換而已失去準確性,所以班級不允許這樣做。
這是正確的做法。 OP不應該對float類型進行任何科學計算。 – patrys
看看打印聲明的力量...
讓我們插入一個打印語句...
x = -5
while x < 5:
if (x == 0):
print 0
x += .01
print x
運行該程序,並圍繞0檢查輸出揭示了問題:
...
-0.13
-0.12
-0.11
-0.1
-0.0900000000001
-0.0800000000001
-0.0700000000001
-0.0600000000001
-0.0500000000001
-0.0400000000001
-0.0300000000001
-0.0200000000001
-0.0100000000001
-6.23077978101e-14
0.00999999999994
0.0199999999999
0.0299999999999
0.0399999999999
0.0499999999999
0.0599999999999
0.0699999999999
0.0799999999999
0.0899999999999
0.0999999999999
0.11
0.12
0.13
...
哦,孩子,這是從來沒有實際上等於零!
解決方案:
使用整數。最可靠的。
x = -500 # times this by a 100 to make it an integer-based program
while x < 500:
if (x == 0):
print 0
x += 1
決不測試浮點運算的平等,而是使用範圍:
delta = 0.00001 #how close do you need to get
point = 0 #point we are interested in
if (point-delta) <= x <= (point+delta):
# do stuff
對於這個微小的邊距,「epsilon」是一個比「delta」更好的名稱選擇,因爲它按照約定表示無限小的微分量,通常對應於某個期望的精度。「delta」通常用作兩個值之間的差異(觀察期望值或當前值先前值)。不像使用i,j和k作爲循環計數器那麼強大,但仍然是一個很好的區別。 – PaulMcG
@PaulMcGuire:根據數學慣例,epsilon和delta都用於小數量。我認爲delta實際上是一個更好的選擇,因爲「epsilon」在浮點運算領域具有特定的含義,這與它在這裏的使用方式不同。一個更好的名字將是'comparisonThreshold',然而=) –
@StephenCanon:你確定嗎?我的工程類都使用epsilon來實現這個目的(也許這是一個「工程師說epsilon,科學家說delta」的東西)。一個「浮點epsilon」和「浮點三角洲」的快速谷歌搜索似乎爲「epsilon」增加了更多的點擊量,並且前幾名都描述了它僅用於此目的。即使是「每個計算機程序員......」的引用都指的是epsilon,或者特別是「機器epsilon」,它是FPU中最小的可區分的差異。你在考慮什麼是「FP算術領域的具體含義」? – PaulMcG
要精確到您的查詢,浮點數被存儲在計算機硬件二進制(基2)分數。所以,即使你在變量中存儲了像0.01這樣的浮點數,計算機也會最終將其轉換爲相應的二進制值。爲方便起見,0.01浮點轉換爲二進制:
0.01 * 2 = 0.02 [0]
0.02 * 2 = 0.04 [0]
0.04 * 2 = 0.08 [0]
0.08 * 2 = 0.16 [0]
0.16 * 2 = 0.32 [0]
0.32 * 2 = 0.64 [0]
0.64 * 2 = 1.28 [0]
0.28 * 2 = 0.56 [0]
0.56 * 2 = 1.12 [1]
...
這種計算將是過於冗長顯示在這裏完全及可能不會在所有的結束。但我想在此陳述的事實是,大多數小數不能完全轉換成二進制分數。因此,您存儲的小數點將近似於機器中存儲的二進制浮點數(顯然不能存儲非常長的二進制值)。所以當計算完成後,你肯定不應該期望精確的浮動值。將x + = 0.01放入代碼就是這種情況。 0.5至它然而轉換的二進制等效值將給出:
0.5 * 2 = 1.0 [1]
所以0.5浮子的二進制等效爲0.1。因爲它在您的機器中完全以二進制表示。你會得到確切的結果。
它與你的代碼或python無關。這只是計算機硬件的工作方式:)
您可能想閱讀[每位計算機科學家應瞭解的浮點算術知識](http://download.oracle.com/docs/cd/E19957-01/806 -3568/ncg_goldberg.html) – Dirk