Skip to content

Commit 7b6c6e0

Browse files
authored
Merge pull request #2960 from spevans/pr_decimal_large_exponent
Decimal: init?(string:) and scanDecimal() should return nil on error.
2 parents cf74d83 + 2d3c2ee commit 7b6c6e0

File tree

2 files changed

+33
-6
lines changed

2 files changed

+33
-6
lines changed

Sources/Foundation/Decimal.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2295,7 +2295,7 @@ extension Scanner {
22952295
repeat {
22962296
buf.advance()
22972297
} while decimalValue(buf.currentCharacter) != nil
2298-
return Decimal.nan
2298+
return nil
22992299
}
23002300
result._exponent += 1
23012301
}
@@ -2315,7 +2315,7 @@ extension Scanner {
23152315
repeat {
23162316
buf.advance()
23172317
} while decimalValue(buf.currentCharacter) != nil
2318-
return Decimal.nan
2318+
return nil
23192319
}
23202320
result._exponent -= 1
23212321
}
@@ -2339,7 +2339,7 @@ extension Scanner {
23392339
while let numeral = decimalValue(buf.currentCharacter) {
23402340
exponent = 10 * exponent + Int32(numeral)
23412341
guard exponent <= 2*Int32(Int8.max) else {
2342-
return Decimal.nan
2342+
return nil
23432343
}
23442344

23452345
buf.advance()
@@ -2350,7 +2350,7 @@ extension Scanner {
23502350
}
23512351
exponent += result._exponent
23522352
guard exponent >= Int32(Int8.min) && exponent <= Int32(Int8.max) else {
2353-
return Decimal.nan
2353+
return nil
23542354
}
23552355
result._exponent = exponent
23562356
}

Tests/Foundation/Tests/TestDecimal.swift

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -749,7 +749,7 @@ class TestDecimal: XCTestCase {
749749
}
750750
}
751751

752-
func test_ScanDecimal() {
752+
func test_ScanDecimal() throws {
753753
let testCases = [
754754
// expected, value
755755
( 123.456e78, "123.456e78" ),
@@ -764,7 +764,7 @@ class TestDecimal: XCTestCase {
764764
]
765765
for testCase in testCases {
766766
let (expected, string) = testCase
767-
let decimal = Decimal(string:string)!
767+
let decimal = try XCTUnwrap(Decimal(string:string))
768768
let aboutOne = Decimal(expected) / decimal
769769
let approximatelyRight = aboutOne >= Decimal(0.99999) && aboutOne <= Decimal(1.00001)
770770
XCTAssertTrue(approximatelyRight, "\(expected) ~= \(decimal) : \(aboutOne) \(aboutOne >= Decimal(0.99999)) \(aboutOne <= Decimal(1.00001))" )
@@ -779,6 +779,33 @@ class TestDecimal: XCTestCase {
779779
return
780780
}
781781
XCTAssertEqual(answer,num,"\(ones) / 9 = \(answer) \(num)")
782+
783+
// Exponent overflow, returns nil
784+
XCTAssertNil(Decimal(string: "1e200"))
785+
XCTAssertNil(Decimal(string: "1e-200"))
786+
XCTAssertNil(Decimal(string: "1e300"))
787+
XCTAssertNil(Decimal(string: "1" + String(repeating: "0", count: 170)))
788+
XCTAssertNil(Decimal(string: "0." + String(repeating: "0", count: 170) + "1"))
789+
XCTAssertNil(Decimal(string: "0e200"))
790+
791+
// Parsing zero in different forms
792+
let zero1 = try XCTUnwrap(Decimal(string: "000.000e123"))
793+
XCTAssertTrue(zero1.isZero)
794+
XCTAssertEqual(zero1._isNegative, 0)
795+
XCTAssertEqual(zero1._length, 0)
796+
XCTAssertEqual(zero1.description, "0")
797+
798+
let zero2 = try XCTUnwrap(Decimal(string: "+000.000e-123"))
799+
XCTAssertTrue(zero2.isZero)
800+
XCTAssertEqual(zero2._isNegative, 0)
801+
XCTAssertEqual(zero2._length, 0)
802+
XCTAssertEqual(zero2.description, "0")
803+
804+
let zero3 = try XCTUnwrap(Decimal(string: "-0.0e1"))
805+
XCTAssertTrue(zero3.isZero)
806+
XCTAssertEqual(zero3._isNegative, 0)
807+
XCTAssertEqual(zero3._length, 0)
808+
XCTAssertEqual(zero3.description, "0")
782809
}
783810

784811
func test_SimpleMultiplication() {

0 commit comments

Comments
 (0)