提问人:amwill04 提问时间:10/16/2019 最后编辑:phuclvamwill04 更新时间:8/2/2022 访问量:961
不同语言的浮点精度
Floating point accuracy with different languages
问:
我目前正在进行坐标之间的距离计算,并且根据所使用的语言得到的结果略有不同。
计算的一部分是计算给定的 .我得到以下结果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
我想试着理解为什么。如果你看过去,就四舍五入而言是唯一“正确”的答案。令我惊讶的是,结果却有所不同。16dp
c
python
这个微小的差异目前正在被放大,超过 000 个位置它正在增加一个不小的距离。
不太确定这是怎么回事。此外,我更要求一个整体的答案,而不是具体的语言。我没有计算科学学位。
更新
我承认,也许这是一个过于宽泛的问题,我想我很好奇为什么因为我的背景不是 CS。我很欣赏评论中发布的博客链接。
更新 2
这个问题源于将服务从 移植到 。 更奇怪的是,我现在无法运行测试,因为距离的总和随多个值而变化。nodejs
go
Go
给定一个坐标列表并计算距离并将它们相加,我得到了不同的结果。我不是在问问题,但看起来很疯狂,会产生不同的结果。go
9605.795975874069
9605.795975874067
9605.79597587407
为了完整起见,以下是我使用的距离计算:
func Distance(pointA Coordinate, pointB Coordinate) float64 {
const R = 6371000 // Earth radius meters
phi1 := pointA.Lat * math.Pi / 180
phi2 := pointB.Lat * math.Pi / 180
lambda1 := pointA.Lon * math.Pi / 180
lambda2 := pointB.Lon * math.Pi / 180
deltaPhi := phi2 - phi1
deltaLambda := lambda2 - lambda1
a := math.Sin(deltaPhi/2)*math.Sin(deltaPhi/2) + math.Cos(phi1)*math.Cos(phi2)*math.Sin(deltaLambda/2)*math.Sin(deltaLambda/2)
c := 2 * math.Atan2(math.Sqrt(a), math.Sqrt(1-a))
d := R * c
return d
}
答:
1赞
Gerd
10/16/2019
#1
通常,浮点数的表示由标准 IEEE 754 定义,我的假设是该标准由所有(主要)编程语言实现。
根据编程语言或使用的数学库,可能会对计算结果产生影响的方面:
评论
0赞
Marek R
8/2/2022
这不是语言问题,而是硬件(CPU 和 FPU 设计)。
0赞
MSalters
8/2/2022
@MarekR:硬件可以使IEEE754更容易或更难实现,但你可以完全在软件中完成IEEE754。
2赞
phuclv
8/19/2020
#2
IEEE-754 只需要基本运算 () 并正确舍入,即误差不得超过 0.5ULP。先验功能,如 、 、 ...非常复杂,因此只建议正确舍入。不同的实现可能会使用不同的算法来计算这些函数的结果,具体取决于空间和时间要求。因此,像您观察到的变化是完全正常的+-*/
sqrt
sin
cos
exp
没有一个标准要求忠实地四舍五入先验功能。IEEE-754 (2008) 建议(但不要求)正确舍入这些函数。
另请参阅
评论
1赞
Eric Postpischil
8/20/2020
“正确舍入”和“忠实舍入”是浮点数中的特定术语,需要谨慎使用。“适当四舍五入”不是一个特别定义的短语;这将取决于上下文中“适当”的含义。“正确”舍入是最严格的:浮点结果必须是无限精确的结果,四舍五入到由舍入规则唯一确定的数字。这并不等同于最多 1/2 ULP 的四舍五入,因为必须遵守平局规则。“忠实”则更宽松:结果可能是紧邻的两个邻居之一。
0赞
Eric Postpischil
8/20/2020
“仅建议适当舍入”一语在“建议”附近有“仅”,尽管它更可能是为了修饰“适当四舍五入”。
2赞
Eric Postpischil
8/20/2020
同样值得注意的是,人类还不知道如何在已知的有界执行时间内以正确的舍入来计算所有“基本”函数(正弦、余弦、对数等)。如果没有新的研究,没有人能够实现满足 IEEE 754 建议的库,并且执行时间有已知的限制。在我的建议下,委员会投票建议忠实地进行四舍五入,但在委员会完成工作后,投票方式发生了变化。
评论
0.6261694290123148
fmt.Printf("%.25f", v)
0.6261694290123147599302911
7
8
cos
cosine
x = 0.8941658257446736; assert(cos(x) == cos(x + argc/1000));