双>字符串>双重转换

发布于 2024-12-09 11:54:17 字数 779 浏览 0 评论 0原文

为了通过网络传输数据,我将 double 转换为 string ,发送它并在接收端将其转换回 double 。 到目前为止,一切都很好。 但我偶然发现了一些我无法解释的奇怪行为

整个示例代码可以在此处找到。 我做什么: 通过 ostringstream 将 double 写入字符串,然后使用 istringstream 将其读入 值发生变化 但是如果我使用函数“strtod(...)”它就可以工作。 (具有相同的outstring

示例(整个代码可以在此处找到):

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>>’导致另一个结果为“strtod”” 请不要回答为什么 IEEE 754 不准确的问题。

To transport data over the network I convert a double to string , send it and on the receiver side convert it back to double.
so far so good.
But I stumbled over some weird behaviour which I'm not able to explain

The whole example code can be found here.
what i do:
Write a double to string via ostringstream, afterwards read it in with istringstream
the value changes
But if i use the function "strtod(...) " it works. (with the same outstring)

Example (the whole code can be found 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 

I wonder why this happens.

The question is: "Why is 'istream >>' leading to another resulst as 'strtod'"
Please don't answer the question why IEEE 754 is no exact.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

聆听风音 2024-12-16 11:54:17

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

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

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

浮点数会让你感到惊讶的原因是 float 和 double
值通常使用有限精度二进制表示
格式。换句话说,浮点数不是实数。
例如,在您机器的浮点格式中,它可能是
不可能精确地表示数字0.1。打个比方,
不可能精确地表示十进制三分之一的数字
格式(除非您使用无限数量的数字)......
消息是某些浮点数不能总是
准确地表示,因此比较并不总是达到您想要的效果
他们要做的事。换句话说,如果计算机实际上乘以 10.0
到 1.0/10.0 时,它可能不会完全恢复到 1.0。

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

...某些机器的浮点精度更高
计算寄存器而不是存储在内存中的双精度值,其中
当看起来两个
值必须相等。

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 时,通常不会发生这种情况,但您的情况可能会有所不同。

Why are they might be different:
http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.16

Floating point is an approximation...

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

The reason floating point will surprise you is that float and double
values are normally represented using a finite precision binary
format. In other words, floating point numbers are not real numbers.
For example, in your machine's floating point format it might be
impossible to exactly represent the number 0.1. By way of analogy,
it's impossible to exactly represent the number one third in decimal
format (unless you use an infinite number of digits)....
The message is that some floating point numbers cannot always be
represented exactly, so comparisons don't always do what you'd like
them to do. In other words, if the computer actually multiplies 10.0
by 1.0/10.0, it might not exactly get 1.0 back.

How to compare floating point:
http://c-faq.com/fp/strangefp.html

...some machines have more precision available in floating-point
computation registers than in double values stored in memory, which
can lead to floating-point inequalities when it would seem that two
values just have to be equal.

http://www.parashift.com/c++-faq-lite/newbie.html#faq-29.17
Here's the wrong way to do it:

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

If what you really want is to make sure they're "very close" to each other (e.g., if variable a contains the value 1.0 / 10.0 and you want to see if (10*a == 1)), you'll probably want to do something fancier than the above:

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

There are many ways to define the isEqual() function, including:

 #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
 }

Note: the above solution is not completely symmetric, meaning it is possible for isEqual(x,y) != isEqual(y,x). From a practical standpoint, does not usually occur when the magnitudes of x and y are significantly larger than epsilon, but your mileage may vary.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文