admin管理员组

文章数量:1023133

According to Google Test's documentation about floating point comparison, EXPECT_DOUBLE_EQ and ASSERT_DOUBLE_EQ verify that the two double values val1 and val2 are approximately equal, to within 4 ULPs (Units in the Last Place) from each other.

The following code example, however, fails the test even though the difference in the two doubles occur in 2 ULPs.

TEST(Foo, doubles_match)
{
   ASSERT_DOUBLE_EQ(0.62469504755442462, 0.62469504755442407);
}

Results:

error: Expected equality of these values:
0.62469504755442462
0.62469504755442407

What am I missing?

According to Google Test's documentation about floating point comparison, EXPECT_DOUBLE_EQ and ASSERT_DOUBLE_EQ verify that the two double values val1 and val2 are approximately equal, to within 4 ULPs (Units in the Last Place) from each other.

The following code example, however, fails the test even though the difference in the two doubles occur in 2 ULPs.

TEST(Foo, doubles_match)
{
   ASSERT_DOUBLE_EQ(0.62469504755442462, 0.62469504755442407);
}

Results:

error: Expected equality of these values:
0.62469504755442462
0.62469504755442407

What am I missing?

Share Improve this question asked Nov 18, 2024 at 21:08 Constantinos GlynosConstantinos Glynos 3,2062 gold badges17 silver badges33 bronze badges 4
  • 1 The difference between 0.6246950475544246206283105493639595806598663330078125 and 0.62469504755442406551679823678568936884403228759765625 is 0.00000000000000055511151231257827021181583404541015625, which is 5 ULPs. You can count the number of steps needed using std::nextafter. Unless I'm on a different page for what ULPs means in this context. – Eljay Commented Nov 18, 2024 at 21:26
  • 1 Those are text representations of floating-point values. It is not self-evident that the corresponding floating-point values differ by 2 ULPs. Subtract the floating-point values and see what the difference is. Note that ULP refers to the internal representations (typically binary) of the values, not to the text that was converted to the values. – Pete Becker Commented Nov 18, 2024 at 21:28
  • 1 Or better put them into 10 base convert where it is obvious that they differ by 5 ULP. Output in FP hexadecimal a format is also helpful for checking exact mantissa values (or transferring them between programs reliably as text). – Martin Brown Commented Nov 18, 2024 at 22:18
  • Thank you for your responses! I am aware of the IEEE standardization on double precision, whereby the precision is determined by ~52 bits (1 sign + 11 exponent + ~52 precision). I was thinking this might have been the reason, but it also backfired because the difference in the numbers for the full extent of the precision range is more than 5 ULPs. Technically, it is 37 ULPs. Please see this code example: rextester/OIUA56796. Also, according to the compiler explorer, I think that the numbers are stringified: godbolt./z/EYb6T8cjT – Constantinos Glynos Commented Nov 19, 2024 at 12:05
Add a comment  | 

1 Answer 1

Reset to default 0

The numbers mentioned in the question are 5 ULPs apart (considering binary 64-bit IEEE-754 numbers). You can verify this with this program:

#include <bit>
#include <cstdint>
#include <print>

int main() {
    const std::uint64_t a = std::bit_cast<std::uint64_t>(0.62469504755442462);
    const std::uint64_t b = std::bit_cast<std::uint64_t>(0.62469504755442407);
    std::print("{:016x}\n", a);
    std::print("{:016x}\n", b);
    std::print("diff: {}\n", a - b);
}

It outputs:

3fe3fd8077e7057a
3fe3fd8077e70575
diff: 5

According to Google Test's documentation about floating point comparison, EXPECT_DOUBLE_EQ and ASSERT_DOUBLE_EQ verify that the two double values val1 and val2 are approximately equal, to within 4 ULPs (Units in the Last Place) from each other.

The following code example, however, fails the test even though the difference in the two doubles occur in 2 ULPs.

TEST(Foo, doubles_match)
{
   ASSERT_DOUBLE_EQ(0.62469504755442462, 0.62469504755442407);
}

Results:

error: Expected equality of these values:
0.62469504755442462
0.62469504755442407

What am I missing?

According to Google Test's documentation about floating point comparison, EXPECT_DOUBLE_EQ and ASSERT_DOUBLE_EQ verify that the two double values val1 and val2 are approximately equal, to within 4 ULPs (Units in the Last Place) from each other.

The following code example, however, fails the test even though the difference in the two doubles occur in 2 ULPs.

TEST(Foo, doubles_match)
{
   ASSERT_DOUBLE_EQ(0.62469504755442462, 0.62469504755442407);
}

Results:

error: Expected equality of these values:
0.62469504755442462
0.62469504755442407

What am I missing?

Share Improve this question asked Nov 18, 2024 at 21:08 Constantinos GlynosConstantinos Glynos 3,2062 gold badges17 silver badges33 bronze badges 4
  • 1 The difference between 0.6246950475544246206283105493639595806598663330078125 and 0.62469504755442406551679823678568936884403228759765625 is 0.00000000000000055511151231257827021181583404541015625, which is 5 ULPs. You can count the number of steps needed using std::nextafter. Unless I'm on a different page for what ULPs means in this context. – Eljay Commented Nov 18, 2024 at 21:26
  • 1 Those are text representations of floating-point values. It is not self-evident that the corresponding floating-point values differ by 2 ULPs. Subtract the floating-point values and see what the difference is. Note that ULP refers to the internal representations (typically binary) of the values, not to the text that was converted to the values. – Pete Becker Commented Nov 18, 2024 at 21:28
  • 1 Or better put them into 10 base convert where it is obvious that they differ by 5 ULP. Output in FP hexadecimal a format is also helpful for checking exact mantissa values (or transferring them between programs reliably as text). – Martin Brown Commented Nov 18, 2024 at 22:18
  • Thank you for your responses! I am aware of the IEEE standardization on double precision, whereby the precision is determined by ~52 bits (1 sign + 11 exponent + ~52 precision). I was thinking this might have been the reason, but it also backfired because the difference in the numbers for the full extent of the precision range is more than 5 ULPs. Technically, it is 37 ULPs. Please see this code example: rextester/OIUA56796. Also, according to the compiler explorer, I think that the numbers are stringified: godbolt./z/EYb6T8cjT – Constantinos Glynos Commented Nov 19, 2024 at 12:05
Add a comment  | 

1 Answer 1

Reset to default 0

The numbers mentioned in the question are 5 ULPs apart (considering binary 64-bit IEEE-754 numbers). You can verify this with this program:

#include <bit>
#include <cstdint>
#include <print>

int main() {
    const std::uint64_t a = std::bit_cast<std::uint64_t>(0.62469504755442462);
    const std::uint64_t b = std::bit_cast<std::uint64_t>(0.62469504755442407);
    std::print("{:016x}\n", a);
    std::print("{:016x}\n", b);
    std::print("diff: {}\n", a - b);
}

It outputs:

3fe3fd8077e7057a
3fe3fd8077e70575
diff: 5

本文标签: cASSERTDOUBLEEQ fails on 2 ULPsStack Overflow