2017-03-13 6 views
1

私は、(他の演算の中で)加算のオーバーフローチェックを作成しようとしていますが、intとlongのために書いた単体テストはうまくいきましたが、それを浮かべるように伸ばす。C++の浮動小数点減算は発生していないようです

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 

原因と、浮動小数点値最大値から1を減算を認識しないように見えます不等式はfalseと評価されます。 write文は、最大値から1を引いた値が最大値よりも小さく評価されないことを確認します。

ありがとうございました。

+7

浮動小数点数は奇妙です。 'max'は非常に大きいので、' max-1'は表現できないので、 'max'に丸められます。 – NathanOliver

+0

@ NathanOliver:確かにそうです。 1e + 308を格納するには何ビットの仮数が必要ですか? –

+0

max + 1は未定義の振る舞いをしますが、単純な差分演算には使用できないmaxに対してなぜ値を選ぶのですか?まっすぐな比較だけでは(やや小さな値との比較ではない)できない場合は、操作できるCANの数が少ないほうが含まれるはずです。 – Wilhelm

答えて

0

プログラムが正常に動作していますが、浮動小数点値のオーバーフローはありません。あなたの最初の数字がゼロに丸められたからです。

は1e30

に最初の番号を設定しようともこれをコーディングしよう:

(1E21 + 1E0)-1e21 = 0が、1e21-1e21 + 1E0 = 1E0

+0

"ゼロに丸められた"変数とその理由を教えてください。 – Wilhelm

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"を読むよりもうまくいくことはありません。

関連する問題