La saggezza comune secondo cui i numeri in virgola mobile non possono essere confrontati per l'uguaglianza è inaccurata. I numeri in virgola mobile non sono diversi dagli interi: se si valuta "a == b", si otterrà vero se si tratta di numeri identici e falso altrimenti (con la consapevolezza che due NaN ovviamente non sono numeri identici).
Il vero problema è questo: se ho fatto alcuni calcoli e non sono sicuro che i due numeri che devo confrontare siano esattamente corretti, allora? Questo problema è lo stesso per il virgola mobile come per gli interi. Se si valuta l'espressione intera "7/3 * 3", non comparerà uguale a "7 * 3/3".
Supponiamo quindi di aver chiesto "Come confrontare i numeri interi per l'uguaglianza?" in una situazione del genere. Non esiste una risposta singola; cosa dovresti fare dipende dalla situazione specifica, in particolare che tipo di errori hai e che cosa vuoi ottenere.
Ecco alcune possibili scelte.
Se si desidera ottenere un risultato "vero" se i numeri matematicamente esatti fossero uguali, è possibile provare a utilizzare le proprietà dei calcoli eseguiti per dimostrare che si ottengono gli stessi errori nei due numeri. Se ciò è fattibile e si confrontano due numeri risultanti da espressioni che darebbero uguali numeri se calcolati esattamente, allora si otterrà "vero" dal confronto. Un altro approccio è che è possibile analizzare le proprietà dei calcoli e dimostrare che l'errore non supera mai un determinato importo, forse un importo assoluto o un importo relativo a uno degli input o uno degli output. In tal caso, puoi chiedere se i due numeri calcolati differiscono al massimo da tale importo e restituire "vero" se rientrano nell'intervallo. Se non riesci a provare un limite di errore, potresti indovinare e sperare per il meglio. Un modo di indovinare è valutare molti campioni casuali e vedere quale tipo di distribuzione ottieni nei risultati.
Naturalmente, poiché impostiamo il requisito di ottenere "vero" solo se i risultati matematicamente esatti sono uguali, abbiamo lasciato aperta la possibilità che tu diventi "vero" anche se sono ineguali. (In effetti, possiamo soddisfare il requisito restituendo sempre "vero". Questo semplifica il calcolo ma è generalmente indesiderabile, quindi discuterò di migliorare la situazione di seguito.)
Se si desidera ottenere un risultato "falso" se i numeri matematicamente esatti non fossero uguali, è necessario dimostrare che la valutazione dei numeri produce numeri diversi se i numeri matematicamente esatti non fossero uguali. Ciò può essere impossibile a scopi pratici in molte situazioni comuni. Quindi consideriamo un'alternativa.
Un requisito utile potrebbe essere quello di ottenere un risultato "falso" se i numeri matematicamente esatti differiscono di più di un certo importo. Ad esempio, forse calcoleremo dove ha viaggiato una palla lanciata in un gioco per computer e vogliamo sapere se ha colpito una mazza. In questo caso, vogliamo certamente diventare "veri" se la palla colpisce la mazza e vogliamo diventare "falsi" se la palla è lontana dalla mazza, e possiamo accettare una risposta "vera" errata se la palla dentro una simulazione matematicamente esatta ha mancato la mazza ma si trova a un millimetro di distanza dalla mazza. In tal caso, dobbiamo dimostrare (o indovinare / stimare) che il nostro calcolo della posizione della palla e della posizione della mazza presenta un errore combinato di massimo un millimetro (per tutte le posizioni di interesse). Questo ci consentirebbe di tornare sempre "
Quindi, come decidere cosa restituire quando si confrontano i numeri in virgola mobile dipende molto dalla situazione specifica.
Per quanto riguarda il modo in cui si provano i limiti di errore per i calcoli, questo può essere un argomento complicato. Qualsiasi implementazione in virgola mobile che utilizza lo standard IEEE 754 in modalità arrotondata al più vicino restituisce il numero in virgola mobile più vicino al risultato esatto per qualsiasi operazione di base (in particolare moltiplicazione, divisione, addizione, sottrazione, radice quadrata). (In caso di pareggio, arrotondare in modo che il bit basso sia uniforme.) (Prestare particolare attenzione alla radice quadrata e alla divisione; l'implementazione del linguaggio potrebbe utilizzare metodi non conformi a IEEE 754 per quelli.) A causa di questo requisito, sappiamo che il l'errore in un singolo risultato è al massimo 1/2 del valore del bit meno significativo. (Se fosse più, l'arrotondamento sarebbe andato a un numero diverso che è entro 1/2 del valore.)
Andare avanti da lì diventa sostanzialmente più complicato; il passaggio successivo sta eseguendo un'operazione in cui uno degli ingressi ha già qualche errore. Per espressioni semplici, questi errori possono essere seguiti attraverso i calcoli per raggiungere un limite all'errore finale. In pratica, ciò viene fatto solo in alcune situazioni, come lavorare in una biblioteca di matematica di alta qualità. E, naturalmente, è necessario un controllo preciso su quali operazioni vengono eseguite. I linguaggi di alto livello spesso danno al compilatore un po 'di gioco, quindi potresti non sapere in quale ordine vengono eseguite le operazioni.
C'è molto di più che potrebbe essere (ed è) scritto su questo argomento, ma devo fermarmi qui. In sintesi, la risposta è: non esiste una routine di libreria per questo confronto perché non esiste un'unica soluzione adatta alla maggior parte delle esigenze che vale la pena inserire in una routine di libreria. (Se il confronto con un intervallo di errore relativo o assoluto è sufficiente per te, puoi farlo semplicemente senza una routine di libreria.)