From 665266910475070a274410afe8b7274dc6f7131b Mon Sep 17 00:00:00 2001 From: Benjamin Barenblat Date: Thu, 14 Apr 2022 18:20:16 +0100 Subject: [PATCH] Round floats using round(x), not static_cast(x + 0.5) Forwarded: yes Applied-Upstream: https://github.com/abseil/abseil-cpp/commit/d96e287417766deddbff2d01b96321288c59491e Adding 0.5 to an IEEE float may cause one bit of precision loss, which is enough to change the result in certain cases. For example, static_cast(std::round(0.49999999999999994)) == 0 static_cast(0.49999999999999994 + 0.5) == 1 The author works at Google. Upstream applied this patch as Piper revision 369926519 and exported it to GitHub; the Applied-Upstream URL above points to the exported commit. Gbp-Pq: Name float-rounding.diff --- absl/time/duration_test.cc | 4 ++-- absl/time/time.h | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/absl/time/duration_test.cc b/absl/time/duration_test.cc index fb28fa9..a3617e7 100644 --- a/absl/time/duration_test.cc +++ b/absl/time/duration_test.cc @@ -1320,7 +1320,7 @@ TEST(Duration, SmallConversions) { EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0)); // TODO(bww): Is the next one OK? - EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(0.124999999e-9)); + EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(0.125e-9, 0))); EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.125e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 4, absl::Seconds(0.250e-9)); EXPECT_EQ(absl::Nanoseconds(1) / 2, absl::Seconds(0.375e-9)); @@ -1330,7 +1330,7 @@ TEST(Duration, SmallConversions) { EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(0.875e-9)); EXPECT_EQ(absl::Nanoseconds(1), absl::Seconds(1.000e-9)); - EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(-0.124999999e-9)); + EXPECT_EQ(absl::ZeroDuration(), absl::Seconds(std::nextafter(-0.125e-9, 0))); EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.125e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 4, absl::Seconds(-0.250e-9)); EXPECT_EQ(-absl::Nanoseconds(1) / 2, absl::Seconds(-0.375e-9)); diff --git a/absl/time/time.h b/absl/time/time.h index 2df6858..48982df 100644 --- a/absl/time/time.h +++ b/absl/time/time.h @@ -1352,7 +1352,7 @@ constexpr Duration MakeDuration(int64_t hi, int64_t lo) { inline Duration MakePosDoubleDuration(double n) { const int64_t int_secs = static_cast(n); const uint32_t ticks = static_cast( - (n - static_cast(int_secs)) * kTicksPerSecond + 0.5); + std::round((n - static_cast(int_secs)) * kTicksPerSecond)); return ticks < kTicksPerSecond ? MakeDuration(int_secs, ticks) : MakeDuration(int_secs + 1, ticks - kTicksPerSecond); -- 2.30.2