【问题标题】:Visual C++ values differ while printing and debugging?打印和调试时 Visual C++ 值不同?
【发布时间】:2013-11-08 10:22:04
【问题描述】:

我正在检查一段代码。一切都是正确的,但我无法理解的概念。

double a = 0.001;
double b = 0.001;
double c = a * b;

printf ("%lf", c);

在 Visual c++ 中调试时,当我在第 3 行之后将鼠标指向 c 时,它显示 9.999999999999995e-007,但在打印时显示正确结果,即 0.000001。我想知道它在调试工具提示中显示的实际值以及它是如何表示和转换的。

【问题讨论】:

  • 只是为了澄清......在运行第 3 行后你得到了错误的 c 值??
  • 没有。实际上它是在调试工具提示中以科学计数法(9.999999999999995e-007)显示的精确值。在 printf 中打印后它是正确的,即 0.000001。我想知道它是如何转换和重新转换的。
  • 好吧,printf 打印的值会四舍五入到默认精度,除非另有说明。 en.cppreference.com/w/cpp/io/c/fprintf:Precision specifies the minimum number of digits to appear after the decimal point character. The default precision is 6.

标签: c++ c visual-c++ visual-studio-debugging


【解决方案1】:

这是 printf 进行四舍五入的结果。

printf 格式 %lf 舍入到默认精度。从我的脑海中,我认为默认值为 6,这就是你得到 0.000001 的原因。

调试器显示双精度的实际内容。由于浮点运算的性质,0.001 * 0.001 的结果实际上并不是 0.000001,而是一个近似值,虽然相差很小。

通过使用其他格式,您可以看到差异。例如。试试 printf("%.15e", c);

【讨论】:

  • 是的,它的尾数和指数形式。但是,如果您查看 0.000001 的科学记数法,它将是 1.0000000000000000e-006,那么为什么它会转换为 9.999999999999995e-007。 0.001 * 0.001 两者都是完全确定的,并且会精确和完美的结果 0.000001 所以为什么需要近似值。它不像我将 7 除以 3。
  • @BharatSharma IEEE-754 double 将尾数存储在基数 2 中,而不是基数 10。0.001 和 0.000001 都不能精确地以基数 2 表示。请参阅 binaryconvert.com/result_double.html?decimal=048046048048049binaryconvert.com/…
  • @gx 好的,我同意它如何在打印时重新转换为 0.000001。如果它可以在这里正确地重新转换,那么为什么它在调试中不正确。我已经从cs.duke.edu/~raw/cps104/TWFNotes/floating.html 读过它,这就是我想知道这个概念的原因。
  • @gx_ 好的,我现在明白了。您可以将其解释为会更好的答案。
【解决方案2】:

从 double/float 到字符串的转换有不同的实现,基于这些实现,您会得到不同的结果。我知道的最准确的实现是std::sringstream,我知道至少在IOS设备上它与printf不同。

据我所知,Visual Studio 界面是用 C# 编码的,因此您可能想了解 C# 如何将双精度转换为字符串以获得您正在寻找的答案。

拉兹万。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-02-10
    • 1970-01-01
    • 2017-02-27
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2020-02-11
    相关资源
    最近更新 更多