如何确认不同的结果是否是由于浮点处理的差异
How to confirm whether different results are due to differences in floating point handling?
我已经将一个相对简单的算法从C++转换为Java,该算法对double
类型的数字执行大量计算,但在两个平台上运行该算法,但在同一台机器上会产生略有不同的结果。该算法对大量的double和int进行乘法和求和。我在Java算法中把int转换为double;C算法不进行投射。
例如,在一次运行中,我得到了以下结果:
- (Java)64684970
- (C++)65296408
(打印忽略小数位)
当然,我的算法中可能会有错误,但在我开始花时间调试之前,有没有可能用C++和Java中不同的浮点处理来解释这种差异?如果是,我能证明这就是问题所在吗?
更新-类型不同的地方是两个int之间的乘积,然后将其添加到一个运行的双整数中。修改了C代码,目前在两者中:
mydouble += (double)int1 * (double)int2
您可以使用相同的精度为每个算法添加舍入。这将允许每个计算以相同的方式处理数据。如果你使用它,它将消除算法的问题,因为对于C++和Java版本,数据在方程的每一步都将使用相同的精度
AFAIK在两个c++编译器版本之间,双文本的值有时会发生变化(用于将源转换为下一个最佳双值的算法发生变化)。
此外,在一些cpu上,浮点寄存器大于64/32位(更大的范围和精度),这对结果的影响取决于编译器和JIT如何将值移入和移出这些寄存器——这可能在java和c++之间有所不同。
Java使用strictftp关键字来确保只使用64/32位的精度,但这会带来运行时成本。还有大量选项可以通过抛出IEEE标准制定的保证性/规则来影响c++编译器如何处理和优化浮点计算。
如果算法基本相同,那么可以检查相同输入的第一个差异出现在哪里。
在Java中,double是一个64位浮点数。在C++中,double是一个保证至少具有32位精度的浮点数。
要找出系统上C++double的实际大小(以字节为单位),请使用sizeof(double)。
如果结果是sizeof(double)==8,那么几乎可以肯定的是,这种差异是由于从一种语言到另一种语言的翻译中的错误,而不是浮点数处理中的差异。
(从技术上讲,字节的大小取决于平台,但大多数现代体系结构使用8位字节。)
- 为什么这个程序的结果是3 "born"?和 4 死
- 是否有必要使用 std::move?这不是已经是一个右值参考了吗?
- 分配给浮点数的积分文字除法 - 为什么结果是错误的?
- C++初始化的结果是什么?
- 我的输出结果是 0 英寸C++.可能是什么问题
- 使用 PIMPL 惯用法,实现是否应始终是类的私有成员?
- 在C++中使用 fread() 来解释这个结果是什么?
- 为什么双算的结果是错误的?
- 抽象类/接口中的空方法是否被认为是一种好的做法?
- 如果我具有调用其其他实例之一的超载函数,它是否被认为是递归功能
- 为什么一个简单的C++程序会有错误的结果?是 #define 引起的吗?
- C++ 指向类的指针和/或引用是否被认为是"movable"?
- 在运行libtorch的模型时获得的结果是不正确的,该模型经过训练并从Pytorch出口
- 使用成员函数更改对象或返回并分配它是否被认为是更好的做法?
- 限制C++中允许的模板参数是否被认为是不良样式?
- 是迭代器增量结果是新的迭代器
- 结果是不同的;C++ 中的 recv(sock,buf,sizeof(buf),0) 和 strlen(buf)
- 非常量表达式的左值到右值转换的结果是常数吗?
- 将Execl命令的结果(是目录列表)输送到父进程
- 如果我将未签名的int添加到负int且算术结果是正面的,会发生什么