当前位置: 首页 > 知识库问答 >
问题:

双精度-MS Visual C 2005 Vs Matlab

林劲
2023-03-14

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

我的问题是,matlab给出了10k输入值,精度为12位小数,但我的c代码将它们设置为15位小数。这意味着matlab中的866.333将用作C中的866.33303。我知道这就是IEEE754的浮点表示法。但是,当我将C输出与matlab输出进行比较时,输入的微小变化确实会对最终结果产生可测量的差异。我可能听起来很奇怪,但这就是梅的观察。我希望我能在这里分享一些代码,但这是非常机密的。如果有人能帮我度过难关,我将不胜感激。

提前谢谢。。。!

共有2个答案

狄鹏
2023-03-14
  1. 浮点数据类型不是由小数位数定义的,而是由用来表示数字的位数以及用来解释这些位数的规则(即IEEE754标准)定义的。
  2. 通常,在两个不同的“环境”(即平台/CPU/编译器等)中实现相同的输出(给定相同的输入)不是一件小事。)。作为一个松散的例子,考虑这样一个事实,html" target="_blank">编译器在计算像a b c这样的表达式时可能有一些自由,可以作为(a b)ca(b c),这在浮点计算中可能给出不同的结果。我强烈建议你重新考虑——获得完全相同的结果真的很重要吗?
  3. 不管2中写了什么,在你的情况下,这是可能的。作为第一步,您应该使用数据的二进制表示,而不是文本表示。换句话说,保存表示数据的字节并将其传递给C代码。例如,不是传递1.0,而是传递0x3FF0000000000000(尽管1.0完全是二进制表示的--这只是一个例子)。

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

蓬英逸
2023-03-14

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

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

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

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

但是,如果您的文本文件是由Matlab(或C)编写的,并将15或16位数字写入数字的文本表示中,那么它应该是整个f-p数字的文本表示,并且在被其他程序读取时,应该被转换为相同的f-p数字。不过请注意,我写的是“应该”,数字至少被翻译了两次,当你把目光从计算机上的数字上移开时,奇怪的事情就会发生。

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

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

总结:

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

此外,除非您在代码中采取特殊措施,否则您的程序可能会随着进展而逐渐失去准确性,从而使所有低阶数字成为可疑的现实。对于您暗示的应用程序,代码背后的科学不太可能支持这样的假设,即在第15个有效数字中不同的两个输出代表不同的值。您的输入所基于的测量的准确性是多少?

 类似资料:
  • 问题内容: java中双值的乘法运算符的保证精度是多少? 例如,2.2 * 100是220.00000000000003,但是220是双精度数。220.00000000000003是220之后的下一个两倍。 问题答案: 乘法工作正常,但不能精确表示为双精度。最接近的双打是: 2.199999999999999733(0x4001999999999999) 2.200000000000000177(

  • 问题内容: 我试图确定双精度的最大精度是多少。在此链接的可接受答案的注释中,Java中的double保持精度 @PeterLawrey将max precision设置为15。 您如何确定呢? 问题答案: @PeterLawrey表示最大精度为15。 实际上,这根本不是他所说的。他说的是: 双精度有15个小数位 他错了。它们的精度为15个十进制 数字 。 任何数字中的小数位数由其对数10的对数给出。

  • 我试图确定double的最大精度是多少。在这个链接中接受的答案的注释中,Java中的Retain precision with double@PeterLawrey声明max precision In 15。 你如何确定这一点?

  • 我想用一个小数点和一个小数位的格式将任何双精度四舍五入为双精度,这样29575.347434将是2.3。 我试着用decimalFormat做这个,但当我试着我只得到了一个29575.3格式的字符串,带有一个,我不知道如何在保留值为双精度的同时去掉所有小数点。

  • 我想要得到一个特定位置附近的所有商店,但似乎我有一个查询字符串的问题。我已经检查了postgis的版本是PostGIS2.5.2_2。我也检查过,看看经度和纬度是否有双精度。 我尝试将查询重写到不同的查询字符串中,但仍然得到相同的错误。 我的实体: 我的存储库接口: 在postgres数据库中工作,但在java应用程序中,它返回一个错误: psqlException:error:“:”处或附近的语

  • 问题内容: 我想知道为什么会出现此错误。(这是Eclipse调试的显示日志) 我不明白为什么我没有得到2.97! 问题答案: 如果需要,您应该已经习惯了。 s以分数形式存储在 二进制 而不是十进制中。因此,例如,仅存储为。 并且不能精确地表示为二进制分数,因此会有一些舍入误差。 您可能还会发现本文很有帮助。

  • 问题内容: 这是一个例子: 这将返回0,而不是应有的0.33333…。 有人知道吗? 问题答案: 这是因为和会被视为您没有另外指定时的处理方式,因此先评估, 然后将转换为。要解决此问题,请尝试,或者明确声明您正在处理double值。

  • 为什么此代码引发此异常: 线程“main”java.lang.ClassCastException:java.lang.Integer无法强制转换为java.lang.Double 而这个,运行良好: 两者都是尝试将整数转换为双精度,对吗?