2017-11-16 3 views
1

文書hereによれば、Swift 3/4 Decimal型は、基数10でNSDecimalNumberに橋渡しされた表現です。しかし、私はNSDecimalNumberを使用しているときに再現しない精密な問題を抱えています。Swiftの小数点精度の問題

let dec24 = Decimal(integerLiteral: 24) 
let dec1 = Decimal(integerLiteral: 1) 
let decResult = dec1/dec24*dec24 
// prints 0.99999999999999999999999999999999999984 

let dn24 = NSDecimalNumber(value: 24) 
let dn1 = NSDecimalNumber(value: 1) 
let dnResult = dn1.dividing(by: dn24).multiplying(by: dn24) 
// prints 1 

Decimal構造体は正確ではないか、何かを誤解していますか?

+0

印刷時に問題の番号が表示されないことを確認しましたか? –

答えて

4

NSDecimalNumber(およびそのオーバーレイタイプDecimalcan represent

... mantissaは、最大38桁の10進整数であり、そしてexponentが-128から整数でmantissa x 10^exponentとして表すことができる任意の数の

127を介して、だから小数画分(最大38桁で)が 表すことができ、正確に、しかし任意ではないNU mbers。特に には、無限に多くの10進数字(repeating decimal)があり、正確にはDecimalと表される にすることはできません。

DecimalNSDecimalNumberの間にも精度差はありません。私たちは、実際の結果と「理論的な結果」との違い を印刷する場合それは明らかになります:

let dec24 = Decimal(integerLiteral: 24) 
let dec1 = Decimal(integerLiteral: 1) 
let decResult = dec1/dec24*dec24 

print(decResult - dec1) 
// -0.00000000000000000000000000000000000016 


let dn24 = NSDecimalNumber(value: 24) 
let dn1 = NSDecimalNumber(value: 1) 
let dnResult = dn1.dividing(by: dn24).multiplying(by: dn24) 

print(dnResult.subtracting(dn1)) 
// -0.00000000000000000000000000000000000016 
+1

ここでの質問は、なぜ「Decimal」では '0.9999999 ... '、NSDecimalNumberでは' 1'と表示されるのかということです。これは数字の印刷方法の違いに過ぎません。 –

+0

@ItaiFerber私は0.999999を得ました....私のテストでは両方のバージョンがあります。 –

+1

@ItaiFerber:OP質問* "Decimal構造体を正確にするべきではありませんか...?" *これが私が答えようとしているものです。 –

3

問題は単純な方法遊び場形式番号のアーチファクトです。

Iは

import Foundation 

let dn1 = Decimal(integerLiteral: 1) 
let dn24 = Decimal(integerLiteral: 24) 
let decResult = dn1/dn24 * dn24 
print(decResult) 

let nsdn1 = NSDecimalNumber(value: 1) 
let nsdn24 = NSDecimalNumber(value: 24) 

let nsdecResult = nsdn1.dividing(by: nsdn24).multiplying(by: nsdn24) 
print(nsdecResult) 
遊び場にこれを入力した遊び場は、最初計算のため 0.99999999999999999999999999999999999984と第2の算出のための 1として右側の番号を表示します。ただし、両方の印刷ステートメントは 0.99999999999999999999999999999999999984と表示されます。

ここでそれを証明する写真があります:

enter image description here

ああ、および(マーティンRが言うように)1月24日は正確に表現できないので、計算は0.99999999999999999999999999999999999984代わりの1を生産する理由がありますDecimal