Quando si confrontano i galleggianti, come si definisce la soglia di differenza?


10

Sto confrontando i float in Java in questo momento e la formula più semplice è:

Math.abs(a - b) < THRESHOLD

Quando assegni un nome alla tua variabile per la soglia di differenza, dovresti chiamarla delta o epsilon ? In particolare, quale dei due è il termine corretto per il valore più piccolo che un numero in virgola mobile può rappresentare?

Il termine è un linguaggio di programmazione specifico o universale tra le lingue?


1
Termini alternativi: "precisione", "risoluzione". Mi piacciono proprio questi;) perché non sembrano eccessivamente tecnici.
stakx,

1
Off-topic: La virgola mobile Guida raccomanda contro di utilizzare questo tipo di confronto quasi uguaglianza.
stakx,

1
@stakx: i termini che suggerisci non sono corretti e hanno significati diversi da quelli richiesti dall'OP. La domanda è dettagliato, sì, ma si basa rispondere facendo riferimento esterno e ha rilevanza per la programmazione quando si tratta di valori in virgola mobile. È costruttivo e in tema.

1
@ GlenH7: non ho mai detto che la domanda non era buona o non rispondeva. In effetti, sono stato io a votarlo. E dal momento che stai affermando che i termini (certamente meno precisi) che ho suggerito sono errati, sarei interessato a sapere perché è così.
stakx,

@stakx - scuse per aver insinuato di aver votato per chiudere. Stavo reagendo di più ai quattro voti stretti sulla domanda al momento.

Risposte:


18

Epsilon in matematica e ingegneria

In matematica e ingegneria in generale:

  • Delta è generalmente usato per fare riferimento a una differenza, che può essere di qualsiasi scala.
  • Epsilon è generalmente usato per indicare una quantità trascurabile.

ed epsilon sembra più appropriato nel tuo caso.


Epsilon in informatica

Nell'informatica in particolare, il termine epsilon si riferisce anche all'espilon macchina che misura la differenza tra 1.0fe il galleggiante più piccolo che è strettamente più grande di 1.0f. Quest'ultimo numero è 1.00000011920928955078125fper float in Java e può essere calcolato con:

float f = Float.intBitsToFloat(Float.floatToIntBits(1f) + 1);

La definizione di epsilon macchina è coerente con l'uso generale di epsilon sopra descritto.


Confronto di galleggianti

Si noti tuttavia che prima di confrontare i galleggianti per "prossimità", è necessario avere un'idea della loro scala. Due galleggianti molto grandi e apparentemente molto diversi possono essere uguali:

9223372036854775808f == 9223372036854775808f + 1000000000f; //this is true!

E inversamente, potrebbero esserci molti possibili valori float (e diversi ordini di grandezza) tra due piccoli float che differiscono per la macchina epsilon "solo". Nell'esempio seguente, ci sono 10.000.000 di valori float disponibili tra smalle f, ma la loro differenza è ancora ben al di sotto del epsilon della macchina:

float small = Float.MIN_VALUE; // small = 1.4E-45
float f = Float.intBitsToFloat(Float.floatToIntBits(small) + 100000000); // f = 2.3122343E-35
boolean b = (f - small < 0.00000011920928955078125f); //true!

L'articolo collegato nella risposta di GlenH7 analizza ulteriormente il confronto dei galleggianti e propone diverse soluzioni per superare questi problemi.


2
-1: Nel software di calcolo scientifico, Epsilon si riferisce a Machine epsilon o Relative epsilon (vedi lo stesso articolo). In genere, questa non è la stessa quantità utilizzata nell'accettare l'uguaglianza approssimativa, perché gli errori di arrotondamento sono multipli di epsilon macchina o epsilon relativi e in genere un ordine di grandezza maggiore di quello.
rwong

1
@rwong Questa è una specializzazione del termine epsilon , e ce ne sono molte altre. In ingegneria in generale, epsilon si riferisce a una piccola quantità o ad un errore e Machine epsilon è compatibile con quell'idea.
Assylias,

@assylias, usando un nome che ha una definizione standard, in un contesto in cui la definizione standard ha senso, ma per qualcosa che non corrisponde alla definizione standard è una ricevuta per problemi.
AProgrammer

@AProgrammer Non sono d'accordo sul fatto che la definizione generale di epsilon non sia applicabile all'informatica.
assylias,

1
@assylias: grazie per il chiarimento. Ho rimosso il mio -1.
rwong,

16

In matematica, delta viene utilizzato per rappresentare una differenza rispetto a un valore, epsilon viene utilizzato per rappresentare un valore di errore arbitrario. In questo caso, epsilon sarebbe il nome convenzionale.


8

Per rispondere direttamente alla tua domanda, vuoi usare il termine epsilon. Più precisamente, è, machine epsilonma l'uso comune fa cadere "macchina" e usa solo epsilon.

Guardando nella mia copia locale di float.hvedo:

#define DBL_EPSILON     2.2204460492503131e-016 /* smallest such that 1.0+DBL_EPSILON != 1.0 */  
#define FLT_EPSILON     1.192092896e-07F        /* smallest such that 1.0+FLT_EPSILON != 1.0 */  
#define LDBL_EPSILON    DBL_EPSILON             /* smallest such that 1.0+LDBL_EPSILON != 1.0 */

E i commenti associati chiariscono che epsilon è il termine a cui ti riferisci.

Ma possiamo anche fare affidamento su alcuni altri riferimenti esterni per verificare che epsilonsia il termine corretto. Vedi qui , qui , qui e infine questa combinazione di tag di query SO . Non sono riuscito a trovare un riferimento diretto allo standard IEEE 754 da citare.


Non me l'hai chiesto, ma ho trovato questo riferimento molto pertinente all'esempio che hai fornito per chiarire la tua domanda.

Dai un'occhiata a questo articolo del blog di Bruce Dawson di Valve sul confronto di valori in virgola mobile per alcune intuizioni sul perché non vuoi usare il confronto che hai suggerito.

Ci sono un sacco di informazioni racchiuse in quell'articolo, ma questo è lo snipppet più rilevante da lì:

Se confrontare float per uguaglianza è una cattiva idea, allora che ne dici di verificare se la loro differenza è all'interno di alcuni limiti di errore o valore epsilon, come questo:

bool isEqual = fabs(f1 – f2) <= epsilon;

Con questo calcolo possiamo esprimere il concetto di due galleggianti abbastanza vicini da volerli considerare uguali. Ma quale valore dovremmo usare per epsilon?
Data la nostra sperimentazione sopra, potremmo essere tentati di usare l'errore nella nostra somma, che era di circa 1,19e-7f. In effetti, c'è anche una definizione in float.h con quel valore esatto, e si chiama FLT_EPSILON.
Chiaramente questo è tutto. I file di intestazione che gli dei hanno parlato e FLT_EPSILON è l'unico vero epsilon!
Solo che è spazzatura. Per i numeri tra 1.0 e 2.0 FLT_EPSILON rappresenta la differenza tra i float adiacenti. Per numeri inferiori a 1,0 un epsilon di FLT_EPSILON diventa rapidamente troppo grande e con numeri abbastanza piccoli FLT_EPSILON potrebbe essere più grande dei numeri che stai confrontando!

Dawson analizza alcune altre considerazioni sulle complessità coinvolte quando si confrontano i galleggianti e si affrontano valori molto piccoli come questo, quindi incoraggio la lettura del resto del suo post.


Potresti voler chiarire la prima parte della tua risposta: l'articolo di Bruce spiega già perché non si dovrebbe usare un epsilon costante (come quelli definiti in un file di intestazione) per il confronto delle tolleranze. Inoltre, in molti casi, un errore di alcuni milioni di ULP non è qualcosa di cui preoccuparsi, perché nella maggior parte delle applicazioni ci preoccupiamo più delle cifre significative più degli errori nelle cifre meno significative, perché la doppia precisione già dà molte più cifre di quelle a cui teniamo.
dal

@rwong - mentre lo leggevo, la domanda era identificare il termine corretto da usare per il nome di una costante. Ecco perché ho fornito il riferimento float.h insieme ad alcuni altri per lavorare epsilon. L'articolo di Dawson è qualcosa che ho trovato durante la ricerca del riferimento IEEE 754 e ho pensato che fosse rilevante ai fini del simplest formulaconfronto. Molti usano questo approccio come primo tentativo, e ho incluso l'articolo di Dawson perché va davvero nelle sfumature di quanto sia complicato il confronto. Quindi ho cercato di rispondere direttamente alla domanda e quindi sottolineare perché non usarlo in quel modo.

5

Questa è una funzione di errore; l'errore assoluto è generalmente chiamato ε (epsilon) o Δ x per una certa quantità x:

ε = | previsto - effettivo |

Δ x = | x 0 - x  |

L'errore relativo è talvolta chiamato η (eta):

η = | 1 - effettivo / atteso |

Ai fini della programmazione absoluteErrore relativeError(o alcune sue abbreviazioni) sono più descrittivi. Se si desidera affermare che l'errore è inferiore a un determinato valore, tale valore verrebbe semplicemente chiamato soglia o tolleranza .

Vedere:


3

Lo definirei "tolleranza".

Forse questo non è il termine matematicamente corretto, ma il semplice fatto che tu ponga la domanda implica per me che né "delta" né "epsilon" sarebbero un buon nome variabile da usare.

Nella mia esperienza, è meglio usare nomi identificativi che abbiano senso per coloro che leggeranno effettivamente il codice. A che serve un nome perfettamente corretto se significa che il lettore deve cercarlo su Wikipedia per capire cosa significa?


+1. Spero sempre che le persone facciano domande ai loro colleghi su queste domande di denominazione e pubblicano qui.
MarkJ,

6
-1, Meglio imparare le convenzioni che evitarle.
Djechlin

+1 perché questo è esattamente lo stesso motivo per cui ho pubblicato questa domanda.
NobleUplift
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.