双>字符串>双重转换

时间:2011-10-12 15:53:57

标签: c++ stl double

要通过网络传输数据,我将double转换为字符串,发送它,然后在接收方将其转换回double。 到现在为止还挺好。 但我偶然发现了一些我无法解释的奇怪行为

可以找到整个示例代码here。 我所做的: 通过ostringstream向字符串写一个double,然后使用istringstream读取它 价值变化 但如果我使用“strtod(...)”功能,它就可以了。 (使用相同的outstring

示例(可以找到整个代码here):

double d0 = 0.0070000000000000001;
out << d0;

std::istringstream in (out.str());
in.precision(Prec);
double d0X_ = strtod(test1.c_str(),NULL);

in >> d0_;
assert(d0 == d0X_); // this is ok
assert(d0 == d0_);   //this fails 

我想知道为什么会这样。

问题是:“为什么'istream&gt;&gt;'导致另一个结果为'strtod'“ 请不要回答为什么IEEE 754不准确的问题。

1 个答案:

答案 0 :(得分:2)

为什么它们可能会有所不同:
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.16

  

浮点数是近似值......

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17

  

浮点数让​​你大吃一惊的原因是浮动和加倍   值通常使用有限精度二进制表示   格式。换句话说,浮点数不是实数。   例如,在您的机器的浮点格式中可能是   不可能完全代表数字0.1。通过类比,   不可能准确地表示十进制中的三分之一   格式(除非你使用无限数量的数字)....   消息是一些浮点数不能总是   完全代表,所以比较并不总是做你想要的   他们这样做。换句话说,如果计算机实际上乘以10.0   按1.0 / 10.0,它可能不会完全恢复1.0。

如何比较浮点数
http://c-faq.com/fp/strangefp.html

  

......有些机器在浮点数上有更多的精度   计算寄存器比存储在存储器中的double值   当它看起来像两个时,会导致浮点不等式   价值必须相等。

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
这是错误的做法:

 void dubious(double x, double y)
 {
   ...
   if (x == y)  // Dubious!
     foo();
   ...
 }

如果您真正想要的是确保它们彼此“非常接近”(例如,如果变量a包含值1.0 / 10.0并且您想要查看是否(10 * a == 1)),你可能想做一些比上面更精彩的事情:

 void smarter(double x, double y)
 {
   ...
   if (isEqual(x, y))  // Smarter!
     foo();
   ...
 }

定义isEqual()函数的方法有很多种,包括:

 #include <cmath>  /* for std::abs(double) */

 inline bool isEqual(double x, double y)
 {
   const double epsilon = /* some small number such as 1e-5 */;
   return std::abs(x - y) <= epsilon * std::abs(x);
   // see Knuth section 4.2.2 pages 217-218
 }

注意:上述解决方案不是完全对称的,这意味着isEqual(x,y)!= isEqual(y,x)是可能的。从实际的角度来看,当x和y的幅度明显大于epsilon时,通常不会发生,但你的里程可能会有所不同。