双精度 - MS visual C ++ 2005与Matlab

时间:2012-04-05 06:55:25

标签: matlab visual-studio-2005 double floating-accuracy double-precision

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

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

提前致谢......!

2 个答案:

答案 0 :(得分:2)

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

Matlab和Visual C ++都不能(没有任意精度库或使用128位f-p数等附加功能)存储超过标准大小的有效数字的双精度数。如果您的程序以任何一种语言向您提供超过15(或16)个十进制数字的数字,则您不能信任任何多余的数字。它们并非来自存储的数字表示,它们已被添加到存储器和屏幕之间的某个位置 - 也许一个“有用的”数字格式器只是扩展了最右边的数字,直到你看到你要求的19位数字(或其他)。

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

如果你使用'text'文件,那么你不是转移数字而是转移数字的表示。如果您的程序将文本'15 .833'读入双变量,则对有效数字中的额外数字所采用的值进行任何假设是不安全的。特别是你不应该假设它们会被设置为0 - 好吧,我想有更多了解C ++的人可能会告诉我们语言标准可以保证这一点,但是Matlab没有,我不认为C ++也做。如果要设置额外数字,请在文本表示中指定它们。即使这样也不能保证您完全按照文本文件中的指定存储值,您的变量将(可能)将最接近的f-p数保存到文本中的值。

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

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

所有前面的guff可能与另一个潜在的问题无关。这个问题可能是你的算法不稳定 - 这是另一个主题。

总结:

  1. 以二进制表示形式从程序到程序传输号码(无论您是使用文件还是消息传递还是其他机制)。
  2. 不要信任双精度浮点数的任何十进制表示中超过15位有效数字。
  3. 此外,除非您在代码中采取特殊措施,否则您的程序可能会随着它们的进展而逐渐失去准确性,从而使所有低位数字成为可疑现实。对于您提示的应用,代码背后的科学不太可能支持这样的假设:在第15位有效数字不同的两个输出代表不同的值。输入所基于的测量精度是多少?

答案 1 :(得分:1)

  1. 浮点数据类型不是由小数位数定义,而是由用于表示数字的位数和用于解释这些位的规则(即IEEE754标准)定义。
  2. 通常,在两个不同的“环境”(即平台/ CPU /编译器等)中实现相同的输出(给定相同的输入)并不是一项微不足道的任务。作为一个简单的例子,考虑一下编译器可能有一些自由来计算像a+b+c这样的表达式(a+b)+ca+(b+c),这在浮点计算中可能给出不同的结果。我强烈建议你重新考虑---获得完全相同的结果真的至关重要吗?
  3. 尽管写在2中,但在你的情况下,它可能是可能的。作为第一步,您应该使用数据的二进制表示,而不是文本。换句话说,保留表示数据的字节并将其传递给C ++代码。例如,传递1.0而不是传递0x3FF0000000000000(尽管1.0完全是二进制可表示的 - 这只是一个例子)。
  4. 当然,一些代码会有所帮助。尝试构建一个玩具示例,在不泄露任何机密信息的情况下显示您的问题。