Actualmente estoy haciendo cálculos de la distancia entre las coordenadas y se han conseguir resultados ligeramente diferentes dependiendo del idioma utilizado.
Parte de la calulation está tomando el cálculo de la cosine
de un dado radian
. Consigo los siguientes resultados
// 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
Me gustaría tratar de entender por qué. Si miras más allá 16dp
c
es la única respuesta "correcta" en términos de redondeo. Lo que estoy sorprendido como es python
tener un resultado diferente.
Esta pequeña diferencia se amplifica en la actualidad y más de 000 de las posiciones que está añadiendo una distancia no despreciable.
No es muy seguro cómo esto es un duplicado. También estoy más pidiendo una respuesta integral en lugar de spicific idioma. No tengo un título en ciencias de computación.
ACTUALIZACIÓN acepto que tal vez esta es una pregunta demasiado amplia supongo que tenía curiosidad de por qué como mi fondo no es CS. Aprecio los enlaces a los blogs que se publicaron en los comentarios.
ACTUALIZACIÓN 2
Esta pregunta arrosé de portar un servicio de nodejs
a go
. Go
es aún más raro como lo estoy ahora incapaz de ejecutar pruebas como la suma de las distancias varía con varios valores.
Dada una lista de coordenadas y el cálculo de la distancia y sumándolos puedo obtener diferentes resultados. Im no haciendo una pregunta, pero parece una locura que go
va a producir resultados diferentes.
9605.795975874069
9605.795975874067
9605.79597587407
Para completar aquí es el cálculo de la distancia que estoy usando:
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
}
En general, la representación de números de punto flotante está definida por el estándar IEEE 754 y mi suposición es que esta norma es implementado por todos los (grandes) lenguajes de programación.
Precisión y redondeo se conocen los problemas y en ocasiones pueden conducir a resultados inesperados .
Aspectos que pueden tener una influencia sobre el resultado de un cálculo en función del lenguaje de programación o biblioteca matemática usada:
- diferentes métodos de cálculo (en su caso: la función coseno podría ser implementado por aproximación numérica con diferentes enfoques)
- diferentes estrategias de redondeo durante cálculo o para la salida final