要通过网络传输数据,我将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不准确的问题。
答案 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时,通常不会发生,但你的里程可能会有所不同。