From 93c31fd71dc15e1319dd01483b6fa919f107f8fa Mon Sep 17 00:00:00 2001 From: Shin Yamamoto Date: Fri, 1 Sep 2023 00:54:19 +0900 Subject: [PATCH] Fix CGFloat.rounded(by displayScale) for a floating point error Where a value is -0.16666666666674246, -0.0 is the rounded value to be expected. However the current implementation returned -0.3333333333333. This is because the floating point error. So this patch truncates it. --- Sources/Extensions.swift | 4 +++- Tests/ExtensionTests.swift | 16 ++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/Sources/Extensions.swift b/Sources/Extensions.swift index 45da38f4..6c4dc840 100644 --- a/Sources/Extensions.swift +++ b/Sources/Extensions.swift @@ -7,7 +7,9 @@ import UIKit extension CGFloat { /// Returns this value rounded to an logical pixel value by a display scale func rounded(by displayScale: CGFloat) -> CGFloat { - return (self * displayScale).rounded(.toNearestOrAwayFromZero) / displayScale + let p = 1.0e9 + let v = (self * p).rounded(.towardZero) / p + return (v * displayScale).rounded(.toNearestOrAwayFromZero) / displayScale } func isEqual(to: CGFloat, on displayScale: CGFloat) -> Bool { return rounded(by: displayScale) == to.rounded(by: displayScale) diff --git a/Tests/ExtensionTests.swift b/Tests/ExtensionTests.swift index b2409abf..f98a2bfa 100644 --- a/Tests/ExtensionTests.swift +++ b/Tests/ExtensionTests.swift @@ -9,4 +9,20 @@ class ExtensionTests: XCTestCase { XCTAssertNotEqual(CGFloat(333.5).rounded(by: 3), 333.66666666666674) XCTAssertTrue(CGFloat(333.5).isEqual(to: 333.66666666666674, on: 3.0)) } + + func test_roundedByDisplayScale_2() { + XCTAssertEqual(CGFloat(-0.16666666666674246).rounded(by: 3), 0.0) + XCTAssertEqual(CGFloat(0.16666666666674246).rounded(by: 3), 0.0) + + XCTAssertEqual(CGFloat(-0.3333333333374246).rounded(by: 3), -0.3333333333333333) + XCTAssertEqual(CGFloat(-0.3333333333074246).rounded(by: 3), -0.3333333333333333) + XCTAssertEqual(CGFloat(0.33333333333374246).rounded(by: 3), 0.3333333333333333) + XCTAssertEqual(CGFloat(0.33333333333074246).rounded(by: 3), 0.3333333333333333) + + XCTAssertEqual(CGFloat(-0.16666666666674246).rounded(by: 2), 0.0) + XCTAssertEqual(CGFloat(0.16666666666674246).rounded(by: 2), 0.0) + + XCTAssertEqual(CGFloat(-0.16666666666674246).rounded(by: 6), -0.16666666666666666) + XCTAssertEqual(CGFloat(0.16666666666674246).rounded(by: 6), 0.16666666666666666) + } }