0

我正在使用 MS Visual C++ 2005 在 C++ 中实现一些数学算法。我的 C++ 代码采用在 Matlab 中生成的 12 位小数精度的 10K 双精度数据类型输入值(例如 866.333333333333)。然后我的代码进行一些计算并给出结果,即机械实体的损坏值,当相同的算法以相同的输入值在其中运行时,它应该与 matlab 输出相同。

我的问题是 matlab 提供 10k 输入值,精度为小数点后 12 位,但我的 c++ 代码使它们精确到小数点后 15 位。这意味着来自 matlab 的 866.333333333333 将在 C++ 中用作 866.33333333333303。我知道这就是 IEEE754 浮点表示。但是,当我将 C++ 输出与 matlab 输出进行比较时,输入的这个非常微小的变化确实会对最终结果产生可衡量的差异。我可能听起来很奇怪,但这可能是观察到的。我希望我可以在这里分享一些代码,但它是非常机密的。如果有人帮助我解决这个问题,我将不胜感激。

提前致谢...!

4

2 回答 2

2

如果这个问题(和任何答案)以有效数字而不是小数位为框架,会更准确。正如 Itamar Katz 暗示的那样,IEEE 标准确实将双精度浮点数存储在 52 位中作为有效位(有些人称之为尾数)。该标准还暗示了一个额外的位,因此双精度数具有 53 个有效位。当二进制数转换为十进制表示时,这将转换为 15 或 16 位有效数字。

Matlab 和 Visual C++ 都不能(没有额外的工具,例如任意精度库或使用 128 位 fp 数)存储超过标准有效数大小的双精度数。如果您的程序以任何一种语言向您显示超过 15(或 16)位十进制数字的数字,则您不能信任任何多余的数字。它们不是来自数字的存储表示,它们是在内存和屏幕之间的某处添加的——也许一个“有用的”数字格式化程序只是扩展了最右边的数字,直到你看到你请求的 19 位数字(管他呢)。

从如何将数字从 C++ 传输到 Matlab 或从 Matlab 传输数字,甚至您确实传输数字的问题并不完全清楚;也许您只是想编写一个 C++ 程序来重现您的 Matlab 程序的结果。(我们在这里做了很多,所以我在这个领域有一些经验。)

如果您使用“文本”文件,那么您传输的不是数字,而是数字的表示。如果您的程序将文本“15.833”读入一个双精度变量,则对有效数字中额外数字所取的值做出任何假设是不安全的。特别是你不应该假设它们将被设置为 0——好吧,我想对 C++ 更了解的人可能会告诉我们语言标准确实保证了这一点,但 Matlab 没有,我不认为 C++也可以。如果要设置额外的数字,请在文本表示中指定它们。即使这样也不能保证您存储的值与文本文件中指定的完全一致,您的变量将(可能)保存与文本中的值最接近的 fp 数。

但是,如果您的文本文件是由 Matlab(或 C++)编写的,并将 15 或 16 位数字写入数字的文本表示,那么它应该是整个 fp 数字的文本表示,并且在被另一个程序读取时,应该被翻译进入相同的 fp 数。但是请注意,我写的是“应该”,并且该数字至少被翻译了两次,当您将视线从计算机上的数字上移开时,会发生奇怪的事情。

在 C++ 和 Matlab 之间进行位精确数据传输的更好选择是使用二进制文件格式,该格式将 double 的所有 64 位存储为 64 位。Matlab MAT 文件格式当然以标准指定的形式存储 IEEE754 数字。

可能所有前面的废话都与另一个潜在的问题无关。这个问题可能是你的算法不稳定——这是另一个话题。

总结一下:

  1. 以二进制表示从程序到程序传输数字(无论您完全使用文件还是消息传递或其他机制)。
  2. 在双精度浮点数的任何十进制表示中,不要信任超过 15 个有效数字。

Furthermore, unless you take special measures in your code, your programs probably gradually lose accuracy as they progress, making all the low-order digits of dubious reality. For the application that you hint at, it's unlikely that the science behind the code supports the hypothesis that two outputs which differ in the 15th significant digit represent different values. What is the accuracy of the measurements on which your inputs are based ?

于 2012-04-05T09:12:14.007 回答
1
  1. 浮点数据类型不是由小数位数定义的,而是由用于表示数字的位数以及用于解释这些位的规则(即 IEEE754 标准)定义的。
  2. 通常,在两个不同的“环境”(即平台/CPU/编译器等)中实现相同的输出(给定相同的输入)并非易事。作为一个松散的例子,考虑编译器在计算表达式时可能有一定的自由度a+b+cas (a+b)+cor a+(b+c),在浮点计算中可能会给出不同的结果。我强烈建议您重新考虑——获得完全相同的结果真的很重要吗?
  3. 尽管 2 中写了什么,但在您的情况下它可能是可能的。作为第一步,您应该使用数据的二进制表示,而不是文本。换句话说,保存代表您的数据的字节并将其传递给您的 C++ 代码。例如,不是通过,而是1.0通过0x3FF0000000000000(尽管1.0完全可以二进制表示——这只是一个例子)。

当然,一些代码会有所帮助。尝试构建一个玩具示例,在不泄露任何机密信息的情况下展示您的问题。

于 2012-04-05T07:41:18.713 回答