2016-11-20 10 views
1

私は以下のwhileループをテストした結果を理解していません。すぐに浮動小数点を持つwhileループの奇妙な結果を説明する方法

var x: Float = 0.0 
var counter = 0 

while x < 1.41 
{ 
    x += 0.1 
    counter += 1 

} 

print (counter) // 15 
print (x) // 1.5 

それはどのように使用しながら、条件のx < 14.1のための結果はx = 1.5を持つことが可能でしょうか?この結果を説明するには?

更新: ともう1つ。 DoubleとFloatの結果が異なるのはなぜですか?

var x: Double = -0.5 
var counter = 0 

while x < 1.0 
{ 
    x += 0.1 
    counter += 1 
} 

print (counter) // 16 
print (x)//1.1 

var x: Float = -0.5 
var counter = 0 

while x < 1.0 
{ 
    x += 0.1 
    counter += 1 
} 

print (counter) // 15 
print (x)//1.0 

アップデート2 と別のもの。 <と< =条件の違いは何故ですか? < =の使用が浮動小数点の意味を持たないことを意味しますか?

var x: Double = 0.0 
var counter = 0 

while x < 1.5 
{ 
    x += 0.1 
    counter += 1 
} 

print (counter) // 15 
print (x) //1.5 


var x: Double = 0.0 
var counter = 0 

while x <= 1.5 
{ 
    x += 0.1 
    counter += 1 
} 

print (counter) // 15 
print (x) //1.5 
+0

'x'は' while'ループの最後の反復の開始時にどのような価値がありますか?その最終反復の最後にはどのような価値がありますか? –

+0

@Hamish Ok、クリア。私はアップデートを追加しました – VYT

+0

複数の異なる質問を1つに組み合わせないでください。代わりに新しい質問の投稿を作成してください! –

答えて

3

他には何がありますか?ループは15回実行されます。 14回目はxが1.4なので、別の0.1を加えて1.5にします。

ループが1.4で終了すると予想される場合は、while条件をチェックする前にxをインクリメントする必要があります。

あなたはループが1.41で終了することが予想される場合は、お使いの増分は間違っている、あなたがそれ141回の反復なって、代わりに

x += 0.01 

を行う必要があります。

2番目の質問については、Floatは精度の欠如のため金銭計算などに使用しないでください。しかし、私は今までDoubleを信じていました。実行15のwhileループは、1.0と報告されている間に実際にはDouble値が1.0未満であると主張しています。我々は1.0からのxをsubstract場合、我々が見ることができるように私たちは、ここでの精度の問題を持っている:

print(1.0-x) 

返す:1.11022302462516e-16

を同時に、Floatは他にunpreciseのようです方向。最後の走行では0.9(0.9 + 5.96046e-08)より少し大きく、次の走行では10より大きくなります。

DoubleFloatが異なる方向に間違っているのは、値がどのように格納されているかという問題であり、数値によって結果が異なる場合があります。たとえば、2.0の場合、実際の値はどちらも大きくなります(Double,4.440892..e-16、Float238419e-07)。 3.0については、Doubleは1.33226e-15で大きく、Floatは7.1525e-07で小さい。

同じ問題が(より:1.0)x.isLessを使用して発生するが、この方法はhttps://developer.apple.com/reference/swift/floatingpoint/1849403-isless

isLessThanOrEqualTo(1.0)のよう<オペレータのための基礎であり、一方、期待どおりに確実に動作するように思われます。

この回答は今のところかなりの疑問なので、誰かがこれについて深い説明をしていれば私は不思議です...

更新

は、より多くの私はそれがあるスウィフト問題の少ない、それについて考えます。基本的には決して正確ではないので、すべての浮動小数点計算でこの問題が発生します。 FloatDoubleの両方が正確ではない場合、Doubleは正確さの2倍です。しかし、これは、==のような比較は、両方が丸められていない限り、浮動小数点値では役に立たないことを意味します。したがって、(あなたの場合は10進数で)既知の精度を持つあなたのループのようなループの良いアドバイスは、あらゆる種類の比較を行う前にその精度に丸めることになります。例えば、これはループを修正するでしょう:

var x: Double = -0.5 
var counter = 0 

while (round(x * 1000)/1000) < 1.0 
{ 
    x += 0.1 
    counter += 1 
} 

print (counter) // 15 
print (x)//1.0 

var x: Float = -0.5 
var counter = 0 

while (round(x * 1000)/1000) < 1.0 
{ 
    x += 0.1 
    counter += 1 
} 

print (counter) // 15 
print (x)//1.0 
+1

これは[最小精度**の単位**](https://en.wikipedia.org/wiki/Unit_in_the_last_place)が入ります。https://developer.apple.com/reference/swift/float/1846050 -ulp – Alexander

+0

@Lupinityはい、同意すると値を丸めるのは良い解決策です! – VYT

関連する問題