难道C和C++标准要求在数学运算math.h上的浮动点(即sqrt,exp,log,sin,...)返回数值最佳的解决方案?
对于给定的(精确且有效的)输入,通常显然不是这些函数的精确浮点输出.但输出是否必须是最接近数学上精确值的可表示值?
如果没有,是否有任何关于精度的要求(可能是平台特定的/在其他标准中?),以便我能够在我的代码中对计算错误进行最坏情况估计?现代实施的数值误差的典型限制是什么?
我正在研究用LLVM编译的语言.只是为了好玩,我想做一些微基准测试.其中一个,我在一个循环中运行了一百万个sin/cos计算.在伪代码中,它看起来像这样:
var x: Double = 0.0
for (i <- 0 to 100 000 000)
x = sin(x)^2 + cos(x)^2
return x.toInteger
Run Code Online (Sandbox Code Playgroud)
如果我使用以下形式使用LLVM IR内联汇编来计算sin/cos:
%sc = call { double, double } asm "fsincos", "={st(1)},={st},1,~{dirflag},~{fpsr},~{flags}" (double %"res") nounwind
Run Code Online (Sandbox Code Playgroud)
这比分别使用fsin和fcos而不是fsincos更快.但是,它比我分别调用llvm.sin.f64and llvm.cos.f64intrinsics,编译调用C math lib函数要慢,至少使用我正在使用的目标设置(x86_64启用了SSE).
似乎LLVM在单/双精度FP之间插入一些转换 - 这可能是罪魁祸首.这是为什么?对不起,我是大会上的新手:
.globl main
.align 16, 0x90
.type main,@function
main: # @main
.cfi_startproc
# BB#0: # %loopEntry1
xorps %xmm0, %xmm0
movl $-1, %eax
jmp .LBB44_1
.align 16, 0x90
.LBB44_2: # %then4
# in Loop: Header=BB44_1 Depth=1 …Run Code Online (Sandbox Code Playgroud) 我有一个程序在Android和Windows下给出了截然不同的结果.当我根据二进制文件验证输出数据包含预期结果时,差异即使非常小(舍入问题)也很烦人,我必须找到解决方法.
这是一个示例程序:
#include <iostream>
#include <iomanip>
#include <bitset>
int main( int argc, char* argv[] )
{
// this value was identified as producing different result when used as parameter to std::exp function
unsigned char val[] = {158, 141, 250, 206, 70, 125, 31, 192};
double var = *((double*)val);
std::cout << std::setprecision(30);
std::cout << "var is " << var << std::endl;
double exp_var = std::exp(var);
std::cout << "std::exp(var) is " << exp_var << std::endl;
}
Run Code Online (Sandbox Code Playgroud)
在Windows下,使用Visual 2015编译,我得到输出:
var is -7.87234042553191493141184764681
std::exp(var) …Run Code Online (Sandbox Code Playgroud) 我目前正在进行坐标之间的距离计算,并且根据所使用的语言得出的结果略有不同。
计算的一部分是计算cosine给定值的radian。我得到以下结果
// cos(0.8941658257446736)
// 0.6261694290123146 node
// 0.6261694290123146 rust
// 0.6261694290123148 go
// 0.6261694290123148 python
// 0.6261694290123148 swift
// 0.6261694290123146 c++
// 0.6261694290123146 java
// 0.6261694290123147 c
Run Code Online (Sandbox Code Playgroud)
我想尝试并了解原因。如果16dp c四舍五入,过去是唯一的“正确”答案。我感到惊讶的是python,结果有所不同。
目前,这种微小的差异正在被放大,并且超过000个位置增加了不小的距离。
不太确定这是如何重复的。另外,我要求的是整体答案,而不是具体的语言。我没有计算机科学学位。
更新 我接受这可能是一个太宽泛的问题,我想我很好奇为什么我的背景不是CS。我感谢评论中发布的博客链接。
更新2
这个问题源于将服务从移植nodejs到go。Go甚至更奇怪,因为距离的总和随多个值而变化,所以我现在无法运行测试。
给定一个坐标列表并计算距离并将它们加在一起,我得到不同的结果。我没有问一个问题,但似乎go会产生不同的结果。
9605.795975874069
9605.795975874067
9605.79597587407
Run Code Online (Sandbox Code Playgroud)
为了完整起见,这里是我正在使用的距离计算:
// cos(0.8941658257446736)
// 0.6261694290123146 node
// 0.6261694290123146 rust
// 0.6261694290123148 go
// 0.6261694290123148 python
// 0.6261694290123148 swift
// 0.6261694290123146 c++
// 0.6261694290123146 java …Run Code Online (Sandbox Code Playgroud)