swiftlang / swift-corelibs-foundation

The Foundation Project, providing core utilities, internationalization, and OS independence
swift.org
Apache License 2.0
5.29k stars 1.13k forks source link

[SR-2980] NSDecimalNumber's .intValue produces incorrect results for numbers with many numbers after the decimal place #4315

Open swift-ci opened 8 years ago

swift-ci commented 8 years ago
Previous ID SR-2980
Radar None
Original Reporter pwicks (JIRA User)
Type Bug
Status Reopened
Resolution
Environment ``` java $ swift --version Apple Swift version 3.0 (swiftlang-800.0.46.2 clang-800.0.38) Target: x86_64-apple-macosx10.9 $ sw_vers ProductName: Mac OS X ProductVersion: 10.11.6 BuildVersion: 15G1004 ``` XCode Version: Version 8.0 (8A218a)
Additional Detail from JIRA | | | |------------------|-----------------| |Votes | 2 | |Component/s | Foundation | |Labels | Bug | |Assignee | None | |Priority | Medium | md5: edd4e608242098a65d37a036b1051abb

duplicates:

is duplicated by:

Issue Description:

For NSDecimalNumbers with a lot of numbers after the decimal point, .intValue is always zero. Experimentally, it looks like the crossover point where .intValue becomes incorrect is around 19 places after the decimal point (but I haven't tested this extensively).

.int64Value has the same behavior. .int32Value, .int16Value and .int8Value do not.

Test Case:

var a = NSDecimalNumber(string: "103.8097165991902834008097165991902834")
a: NSDecimalNumber = {
  Foundation.NSNumber = {
    baseNSValue@0 = <extracting data from value failed>

  }
}
  6> a.intValue
$R2: Int = 0
  7> a.doubleValue
$R3: Double = 103.80971659919028
  8> a.int64Value
$R4: Int64 = 0
  9> a.int32Value
$R5: Int32 = 103
 10> a.int16Value
$R6: Int16 = 103
 11> a.int8Value
$R7: Int8 = 103
 12> var b = NSDecimalNumber(string: "1.1111111111111111111111111111111111111")
b: NSDecimalNumber = {
  Foundation.NSNumber = {
    baseNSValue@0 = <extracting data from value failed>

  }
}
 13> b.intValue
$R8: Int = 0
 14> b.int32Value
$R9: Int32 = 1
swift-ci commented 7 years ago

Comment by Fabian Emmes (JIRA)

I also noticed this bug, using Swift 3.0.1:

Apple Swift version 3.0.1 (swiftlang-800.0.58.6 clang-800.0.42.1)
Target: x86_64-apple-macosx10.9

And indeed it looks as if it depends on the number of decimal places:

 14> NSDecimalNumber(string: "250.229953885078403").int64Value
$R4: Int64 = 250
 15> NSDecimalNumber(string: "250.22995388507840317").int64Value 
$R5: Int64 = 65
 16> NSDecimalNumber(string: "250.2299538850784031744").int64Value 
$R6: Int64 = 0
swift-ci commented 7 years ago

Comment by Andrew Hoos (JIRA)

This seems to be resolved in top of tree master.

martinr448 commented 6 years ago

The problem still exists in Swift 4.2 (Xcode 10):

Welcome to Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1). Type :help for assistance.
  1>  
  2> import Foundation
  3>  
  4> let a = NSDecimalNumber(string: "103.8097165991902834008097165991902834")
a: NSDecimalNumber = 3748538862552120946 x 10^-34
  5> a.int64Value
$R0: Int64 = 0

Another example:

  7> let b = NSDecimalNumber(string: "31.541176470588235294")
b: NSDecimalNumber = 13094432396878683678 x 10^-18
  8> b.int64Value
$R1: Int64 = -5
  9> b.uint64Value 
$R2: UInt64 = 13
martinr448 commented 6 years ago

The wrong results can still be reproduced with Apple Swift version 4.2 (swiftlang-1000.11.37.1 clang-1000.11.45.1) that comes with Xcode 10, therefore I have reopened the issue.

bealex commented 4 years ago

Got this problem with current Swift 5.1.3 (Xcode 11.3.1)

be0aadd9-8960-4c13-b27b-3298be9f43c2 commented 4 years ago

To reproduce on Swift 5.1.3:

$ swift -version
Apple Swift version 5.1.3 (swiftlang-1100.0.282.1 clang-1100.0.33.15)
Target: x86_64-apple-darwin19.3.0
$ swift
import Foundation
print((Decimal(string: "12345.12345678901234")! as NSDecimalNumber).intValue) 
12345
print((Decimal(string: "12345.123456789012345")! as NSDecimalNumber).intValue)
-6101
spevans commented 3 years ago

Linux fix: https://github.com/apple/swift-corelibs-foundation/pull/2925

pietermuller commented 2 years ago

To reproduce with Swift 5.7 on macOS:

$ swift -version
swift-driver version: 1.62.8 Apple Swift version 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50)
Target: arm64-apple-macosx12.0
$ swift repl
Welcome to Apple Swift version 5.7 (swiftlang-5.7.0.127.4 clang-1400.0.29.50).
Type :help for assistance.
  1> import Foundation 
  2> print((Decimal(string: "12345.12345678901234")! as NSDecimalNumber).intValue) 
12345
  3> print((Decimal(string: "12345.123456789012345")! as NSDecimalNumber).intValue)
-6101
xjki commented 1 year ago

Reproducable with Swift 5.9 on macOS:

~$ swift repl
Welcome to Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1).
1> import Foundation
2> print((Decimal(string: "12345.12345678901234")! as NSDecimalNumber).intValue)
12345
3> print((Decimal(string: "12345.123456789012345")! as NSDecimalNumber).intValue)
-6101
tcamin commented 1 year ago
❯ swift repl
Welcome to Apple Swift version 5.9 (swiftlang-5.9.0.128.108 clang-1500.0.40.1).
Type :help for assistance.
  1> import Foundation
  2> let decimal = NSDecimalNumber(value: 10.12)
  3. decimal.intValue
$R0: Int = -8
decimal: NSDecimalNumber = 10119999999999997952 x 10^-18