假设可以使用正确舍入的标准库函数,例如CRlibm中的函数.那么如何计算双精度输入的正确圆角立方根?
引用FAQ时,这个问题不是"[我]面临的实际问题".这有点像家庭作业.但立方根是经常发现的操作,可以想象这个问题是某人面临的实际问题.
由于"最好的Stack Overflow问题中有一些源代码",这里有一些源代码:
y = pow(x, 1. / 3.);
Run Code Online (Sandbox Code Playgroud)
上面没有计算正确的圆形立方根,因为1/3不能完全表示为a double.
补充说明:
的文章介绍如何计算浮点立方根,但推荐牛顿迭代算法的最后一次迭代(S)将不得不做更高精度的算法来计算正确舍入的双精度立方根.这可能是计算它的最佳方式,但我仍在寻找一种利用现有正确舍入标准化功能的快捷方式.
C99包含一个cbrt()函数,但不能指望所有编译器都能正确舍入甚至忠实.CRlibm的设计者本可以选择包含cbrt()在提供的功能列表中,但他们没有.可以参考其他正确舍入的数学函数库中可用的实现.
我有一个程序在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) 我正在使用一些跨平台代码。在 Mac 上它是用 Clang 编译的,在 Windows 上它是用 Visual C++ 编译的。
有一个计算可能很敏感,并且触发断言的 Mac 和 Windows 之间存在差异。最终 acos 结果之间存在差异,但我不清楚为什么。
在这两个平台上,acos 的输入恰好是 -1.0f。在 Visual C++ 中,acos(-1.0f)为 3.14159274。这就是 pi 作为浮点数的值,这正是我所期望的。
但在 macOS 上:
float value = acos(-1.0f);
...计算结果为 3.1415925。这足以引发代码中的问题。acos 是一种对于 float 来说可能不精确的操作 - 我理解这一点。并且不同的编译器可以有不同的acos实现。我只是不清楚为什么 Clang 似乎对如此简单的 acos 结果有问题,而 Visual C++ 却没有。浮点数能够代表 3.14159274,但这不是我得到的结果。
可以使用以下命令从 Xcode 版本的 Clang 中获取准确/Visual C++ 对齐的值:
float value = (float)acos((double)-1.0f);
因此,我可以通过提高精度来解决这个问题,然后将值向下转换回浮点数以保留与 Windows 相同的舍入。我只是在寻找一个理由,说明当 VC++ 编译器似乎不存在精度问题时,为什么需要额外的精度。Clang/Xcode/VC++ 数学库之间也可能存在差异。我只是假设 acos(-1.0) 可能在编译器中更稳定。我在舍入模式中找不到任何差异(即使舍入不是必需的),并且 Xcode 和 Visual Studio 中的新项目也显示出相同的差异。两台机器都是英特尔的。