2011-10-05 6 views
6
codice

successivo mi dà 5,999999999999998 nel risultato, ma risposta giusta è 6.di precisione in Erlang

Alpha = math:acos((4*4 + 5*5 - 3*3)/(2*4*5)) 
Area = 1/2 * 4 * 5 * math:sin(Alpha) 

E 'possibile ottenere 6?

+5

Non è garantito ottenere risultati esatti quando si utilizza l'aritmetica in virgola mobile. Questo argomento è stato trattato molte, molte, molte volte già. – Nayuki

risposta

23

Hai incontrato un problema così comune che ha un proprio sito web, What Every Programmer Should Know About Floating-Point Arithmetic. Il problema è dovuto al modo in cui l'aritmetica in virgola mobile funziona praticamente in tutte le CPU sul mercato che supporta l'aritmetica FP; non è specifico di Erlang.

Se l'aritmetica in virgola mobile regolare non fornisce la precisione o l'accuratezza necessarie, è possibile utilizzare una libreria aritmetica di precisione arbitraria anziché l'aritmetica incorporata. Forse la libreria più conosciuta è la GMP, ma dovresti avvolgerla in NIFs per usarla da Erlang.

C'è at least one pure-Erlang alternative, ma non ho esperienza con esso, quindi non posso personalmente approvarlo.

+0

Questo è sicuramente un must per chiunque esegua l'aritmetica in virgola mobile. – rvirding

+0

Grazie mille per il collegamento – Yola

+0

@WarrenYoung Grazie per le informazioni, l'ho cercato e ho trovato questo: https://github.com/tim/erlang-decimal Ma non sono sicuro se è in sviluppo attivo, ma alcuni le persone hanno forcelle con modifiche e nuove funzionalità. – JHG

8

Il calcolo viene eseguito utilizzando l'aritmetica in virgola mobile standard sull'hardware. A volte si verificano errori di arrotondamento.

Hai davvero bisogno di 15 cifre di precisione?

Per ottenere una "esatta" del valore di più ci sono più opzioni:

> round(Area). % Will round to integer 
6 

o si potrebbe arrotondare a una certa precisione

round(Area * 10000000)/10000000. 
6.0 

Se lo scopo è quello di stampare il valore, allora la stampa con l'output di default per i float ti dà meno precisione.

io:format("~f~n", [Area]). 
6.000000 
ok 

o con una specifica precisione

io:format("~.14f~n", [Area]). 
6.00000000000000 
ok 

HTH