简体   繁体   中英

Why floating point conversion not working?

Why floating point conversion is failing for the smallest positive floating point number?

#include <iostream>
#include <vector>

int main(){
   std::vector<std::string> testStrings;
   float fmax = std::numeric_limits<float>::max(); // maximum value
   float fmin = std::numeric_limits<float>::min(); // maximum value
   std::cout<<fmax<<std::endl;
   std::cout<<fmin<<std::endl;
   
  float result=0;
  bool status=false;
  //below test cases must pass
  testStrings.push_back("10");
  testStrings.push_back("+10");
  testStrings.push_back(" 10 ");
  testStrings.push_back("10.253165");
  testStrings.push_back("10.253165E12");
  testStrings.push_back("11111111111111111111111");
  testStrings.push_back("2e-123546132222");
  testStrings.push_back("3.40282e+38");
  testStrings.push_back("3.40284e+38");
  testStrings.push_back("1.17549e-38"); // This test case is throwing out of range exception

for(std::string temp:testStrings)
{
std::stof(temp);
}

}

I am using the method std::stof for conversion.

The program does not use enough digits to represent the minimum normal float with sufficient accuracy.

The minimum positive normal number in IEEE-754 binary32 is 2 −126 , which is 1.1754943508222875079687365372222456778186655567720875215087517062784172594547271728515625•10^ −38 . However, this is not the number the program in the question passes to strtod . Instead, it has used only six significant digits, “1.17549e-38”. 1.17549•10 −38 is less than 2 −126 , and it is less than it by so much that converting it to float (using the IEEE-754 binary32 format) produces a number less than 2 −126 . The actual number produced is 2 −126 − 31•2 −149 .

So attempting to convert “1.17549e-38” from decimal to float with strtof yields a range error, because it is indeed out of range (out of the normal range; the value is representable, but the C++ standard allows out of range errors for results in the subnormal range).

Lesson: Do not use just six digits. Using three more digits, “1.17549435e-38”, is sufficient that the result of conversion is 2 −126 , and no range error is generated. In general, using nine significant decimal digits is sufficient that converting any IEEE-754 binary32 format to decimal and back will yield the original number. (This value, nine, is reported by std::numeric_limits<float>::max_digits10 .)

See also std::stod throws out_of_range error for a string that should be valid .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM