如果遵循IEEE 754的两种语言,则两种语言的计算都会产生相同的答案
If two languages follow IEEE 754, will calculations in both languages result in the same answers?
我正在将程序从SCILAB代码转换为C 。尤其是一个循环是与原始Scilab代码产生的结果略有不同(这是一条很长的代码,所以我不会将其包括在问题中,但我会尽力总结以下问题)。
问题是,循环的每个步骤都使用上一步中的计算。此外,计算之间的差异仅在第100,000次迭代左右(大约300,000)。
。注意:我将C 程序的输出与使用"格式(25)"的Scilab 5.5.2的输出进行比较。命令。这意味着我要比较25个重要数字。我还想指出,我了解在一定数量的位之后无法保证精确度,但是在评论之前请阅读以下部分。到目前为止,所有计算在两种语言之间最多25位数字。
试图解决这个问题的底部,到目前为止,我已经尝试过:
- 检查所使用的数据类型:
我设法确认Scilab正在使用IEEE 754双打(根据语言文档)。另外,根据Wikipedia的说法,C 并不需要使用IEEE 754进行双打,但是据我所知,我在C 中使用double的任何地方都可以与Scilab的结果匹配。
- 检查先验功能的使用:
我还从每个计算机科学家都知道的有关浮点算术的知识中读到,IEEE不需要精确的函数才能完全舍入。考虑到这一点,我已经比较了这些功能的结果(sin(),cos(),exp()),同样,结果似乎是相同的(最多25位数字)。
- 使用其他功能和预定义值:
我重复了使用SQRT()和POW()的上述步骤。以及PI的值(我在C 中使用M_PI和SCILAB中的%PI)。同样,结果相同。
- 最后,我已经重写了循环(非常仔细),以确保两种语言之间的代码相同。
注意:有趣的是,我注意到,对于上述所有计算,两种语言之间的结果比计算的实际结果(在浮点算术之外)匹配。例如:
使用wolfram alpha = 0.123456789 ....
使用scilab& sin(x)的价值C = 0.12345yyyyy .....
即使一旦使用Scilab或C 计算的值也开始与实际结果(来自Wolfram)不同。每种语言的结果仍然相互匹配。这使我相信,大多数值以相同的方式计算(两种语言之间)。即使IEEE 754不需要它们。
我的原始思维是上面的前三点之一,两种语言之间的实现方式不同。但是从我可以说的一切似乎都产生了相同的结果。
即使这些循环的所有输入都是相同的,结果也可能有所不同吗?可能是因为一个非常小的错误(过去我可以看到25位数字)正在发生随着时间的推移积累吗?如果是这样,我该如何解决此问题?
no,编号系统的格式不能保证功能的等效答案用不同的语言。
函数(例如sin(x)
)可以使用相同的语言(以及不同的语言)以不同的方式实现。sin(x)
功能是一个很好的例子。许多实现将使用带有插值的查找表或查找表。这具有速度优势。但是,某些实现可能会使用泰勒系列来评估该功能。某些实现可能会使用多项式来提出近似值。
具有相同的数字格式是在语言之间解决的一个障碍。功能实现是另一个。
记住,您也需要考虑该平台。使用80位浮点处理器的程序将具有与使用64位浮点软件实现的程序不同的结果。
一些架构提供了使用扩展精度浮点寄存器的功能(例如,内部80个位,与RAM中的64位值相比)。因此,根据计算的结构方式以及用于编译代码的优化级别,可以对相同的计算获得略有不同的结果。
是的,可能会有不同的结果。即使您在同一平台中使用同一编程语言中完全相同的源代码,也可能。有时足以拥有不同的编译器开关;例如,-ffastmath
将导致编译器以速度而不是准确性来优化您的代码,并且,如果您的计算问题一开始没有很好地条件,则结果可能是显着不同的。 。
例如,假设您有此代码:
x_8th = x*x*x*x*x*x*x*x;
计算此方法的一种方法是执行7个乘法。这将是大多数编译器的默认行为。但是,您可能需要通过指定编译器选项-ffastmath
来加快此功能,并且结果代码只有3个乘法:
temp1 = x*x; temp2 = temp1*temp1; x_8th = temp2*temp2;
结果将略有不同,因为有限的精度算术不是关联的,但对于大多数应用程序而言,足够接近。但是,如果您的计算没有充分的条件,那么小错误会很快被放大到一个大错误中。
请注意,Scilab和C 不是使用完全相同的指令序列,或者一个使用FPU,另一个使用SSE,因此可能没有一种方法使它们完全相同。
i Inspectable所评论,如果您的编译器具有_control87()或类似的内容,则可以使用它来更改精度和/或舍入设置。您可以尝试对此进行组合以查看它是否有任何效果,但是再次,即使您设法获得Scilab和C 相同的设置,实际说明序列的差异也可能是问题。
。http://msdn.microsoft.com/en-us/library/e9b52ceh.aspx
如果使用了SSE,我不确定可以调整什么,因为我认为SSE没有80位精度模式。
在32位模式下使用FPU的情况下,如果您的编译器没有_control87之类的内容,则可以使用汇编代码。如果不允许内联装配,则需要调用汇编功能。此示例来自一个旧的测试程序:
static short fcw; /* 16 bit floating point control word */
/* ... */
/* set precision control to extended precision */
__asm{
fnstcw fcw
or fcw,0300h
fldcw fcw
}
- 在C++中将函数压缩为两种方式
- 如何使映射键具有两种不同的数据类型?
- 两种访问I2C总线的方法有什么区别?
- 两种模板示例有什么区别?
- 如何构造可以调用和返回两种不同类型的模板
- 这两种C++语法之间有什么区别?
- 为什么两种不同的对象初始化方式给出不同的输出
- std::cin 从控制台获取两种不同的变量类型,'storing'以后使用第二种类型?
- 定义类模板构造函数的两种方法之间的区别
- 初始化类的两种方法?
- 如何调试两种语言的程序
- 我如何使用GO语言读取可能是两种不同数据类型之一的HDF5属性
- 如果遵循IEEE 754的两种语言,则两种语言的计算都会产生相同的答案
- 是否有一种方法可以更准确地确定两种语言中的哪种语言中的哪种方法
- 如何使用两种不同的语言制作一个程序
- Qt/Gtk+允许同时用两种语言编程吗
- 我如何在VS中链接用两种不同语言(如c++和c#)编写的两个不同项目?
- 使用两种(人类)语言的应用程序
- 具有两个目标和两种语言的生成文件
- 是C/ c++一种语言还是两种语言