Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[SR-8409] Decimal initialized with Double loses precision #3658

Open
swift-ci opened this issue Jul 30, 2018 · 3 comments
Open

[SR-8409] Decimal initialized with Double loses precision #3658

swift-ci opened this issue Jul 30, 2018 · 3 comments

Comments

@swift-ci
Copy link
Contributor

@swift-ci swift-ci commented Jul 30, 2018

Previous ID SR-8409
Radar None
Original Reporter TomasLinhart (JIRA User)
Type Bug
Additional Detail from JIRA
Votes 0
Component/s Foundation
Labels Bug
Assignee None
Priority Medium

md5: 87fa6caf176bfbf5ed96bbc10110c73b

is duplicated by:

  • SR-11514 Decimal.init(_ value: Double) sometimes yields incorrect value

Issue Description:

Decimal precision is a bit strange for a number 456.789. When you initialize Double with 456.789 it holds the number so it is representable, but if you try to convert it to a decimal with Decimal(456.789) it results in 456.7889999999998976 but if you use Decimal(string: "456.789")! it results in a correct decimal with a value 456.789.

I tried also Objective-C, and it works correctly there:

NSDecimalNumber *number = [[NSDecimalNumber alloc] initWithDouble:456.789];
NSLog(@"Number: %f", number.doubleValue);
@belkadan
Copy link

@belkadan belkadan commented Aug 30, 2018

@stephentyrone
Copy link
Member

@stephentyrone stephentyrone commented Aug 30, 2018

This is mostly expected. `456.789 as Double` has the exact value 456.788999999999987267074175179004669189453125, which is not exactly representable as `Decimal`, so it gets rounded to a representable `Decimal` value.

That second rounding appears to be not quite perfect (that's a Foundation bug), but even if Foundation were rounding correctly, the result would not be 456.789. It would be something like 456.78899999999998726707417517900466919 instead.

@spevans
Copy link
Collaborator

@spevans spevans commented Jan 20, 2019

I wonder if a better solution would be to use the .description property of Double:

public init(_ value: Double) {
    self = Decimal(string: value.description) ?? Decimal.nan
}

and Decimal.description:

internal var doubleValue: Double {
    return Double(self.description) ?? Double.nan
} 

Whilst there will be a conversion cost going via a String, it may provide less surprising values overall.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
@shahmishal shahmishal transferred this issue from apple/swift May 5, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants