C ++浮点减法似乎不会发生

时间:2017-03-13 16:07:49

标签: c++ floating-point

我正在尝试为添加(以及其他操作)创建溢出检查,而在我为int编写的单元测试和longs工作正常时,我在尝试将其扩展到浮点数时遇到了一些麻烦。该问题的实质在以下代码中表达:

 1 #include "gtest/gtest.h"
 2 #include <math.h>
 3 #include <cmath>
 4 #include <cfloat>
 5 #include <float.h>
 6 #include <limits>
 7 
 8 
 9 class Test_FloatPfa : public ::testing::Test
10 {
11 public :
12 
13     virtual void SetUp(){}
14     virtual void TearDown(){}
15 };
16 
17 
18 ///////////////////////////////////Basic operator tests above, overflow tests below////////////////
19 
20 TEST_F(Test_FloatPfa, checking_for_FLOAT_sum_overflow)
21 {
22    float numberOne = std::numeric_limits<float>::max(); 
23    float numberTwo = 1.0; 
24    ASSERT_TRUE(numberTwo > numberOne - std::numeric_limits<float>::max());
25 }
26 
27 TEST_F(Test_FloatPfa, checking_for_FLOAT_sum_overflow2)
28 {
29 
30    float number1 = 1.0;
31    float number2 = std::numeric_limits<float>::max(); 
32 
33    ASSERT_EQ ( number2, std::numeric_limits<float>::max() );
34    printf("number1, number2 and limit -1 is: %f \n, %f \n, %f \n",number1, number2, std::numeric_limits<float>::max() -1);
35    ASSERT_TRUE (number2 > std::numeric_limits<float>::max() - number1 );
36 }                                                                                                                                                                                                   
37 
38 
39 

提供以下输出:

Running main() from gtest_main.cc
[==========] Running 2 tests from 1 test case.
[----------] Global test environment set-up.
[----------] 2 tests from Test_FloatPfa
[ RUN      ] Test_FloatPfa.checking_for_FLOAT_sum_overflow
[       OK ] Test_FloatPfa.checking_for_FLOAT_sum_overflow (0 ms)
[ RUN      ] Test_FloatPfa.checking_for_FLOAT_sum_overflow2
number1, number2 and limit -1 is: 1.000000 
, 340282346638528859811704183484516925440.000000 
, 340282346638528859811704183484516925440.000000 
/home/adam/Projects/git/pfa-cpp-lib/PFALib/test/TEst_for_SO.cpp:35: Failure
Value of: number2 > std::numeric_limits<float>::max() - number1
  Actual: false
Expected: true
[  FAILED  ] Test_FloatPfa.checking_for_FLOAT_sum_overflow2 (0 ms)
[----------] 2 tests from Test_FloatPfa (0 ms total)

[----------] Global test environment tear-down
[==========] 2 tests from 1 test case ran. (1 ms total)
[  PASSED  ] 1 test.
[  FAILED  ] 1 test, listed below:
[  FAILED  ] Test_FloatPfa.checking_for_FLOAT_sum_overflow2

 1 FAILED TEST

它似乎无法识别从最大浮点值中减去一个,导致不等式计算为false。 write语句确认最大值减1不会被评估为小于最大值本身。

提前感谢您提供的任何见解。

2 个答案:

答案 0 :(得分:0)

您的程序运行正常,浮点值没有溢出。因为你的第一个数字四舍五入为零。

尝试将第一个数字设置为1e30

也尝试编写代码:

(1e21 + 1e0)-1e21 = 0但是1e21-1e21 + 1e0 = 1e0

答案 1 :(得分:0)

IEEE754单精度(32位)浮点类型存储6到9个有效精度数字的数字。 要准确地减去1来进行预期的计算,需要39个有效的准确数字。这远远超出了可能的范围。

简而言之,这是因为单个精度浮点值存储在3个部分中:

  • 一个1位的标志,
  • 8位偏置指数和
  • 一个23位的尾数。

浮点数的最大值是 -

340282346638528859811704183484516925440 
with sign=0, biased exponent=254, mantissa=8388607
and hexadecimal representation 0x7F7FFFFF

可以表示的下一个最高数字将使尾数减少1.这给出了 -

340282326356119256160033759537265639424 
with sign=0, exponent=254, mantissa=8388606
and hexadecimal representation 0x7F7FFFFE

浮点类型的操作不像整数那样环绕。相反,他们明确地为超出范围的结果产生无限或非数字的“NaN”值。

在这种情况下,你为什么不进行有问题的操作并检查它是否没有溢出std::isfinite

有关单精度浮点表示的更多基础知识,请参阅"Single-precision floating-point format"

但是,如果您真的想了解浮点数学的工作原理及其对数字编程的影响,那么您最好不要阅读David Goldberg撰写的"What Every Computer Scientist Should Know About Floating-Point Arithmetic"