Come decidere correttamente quale sia l'errore di arrotondamento appropriato per una funzione matematica?

3

Nello spazio della geometria 3D, ho bisogno di calcolare la grandezza del prodotto incrociato di due Line3D perché voglio verificare se queste due linee sono "parallele" l'una all'altra.

Line3D è costituito da 4 campi, x1 , y1 , x2 , y2 che denota i due punti. il x e y sono del tipo double

In teoria, due linee sono parallele se il prodotto incrociato dei loro vettori unitari è uguale a zero.

Ma in pratica, il tipo C # double ha errori di arrotondamento nell'operazione aritmetica. Quindi ho bisogno di prescriverti una tolleranza per questo. Come dovrei procedere per decidere quale sia l'entità corretta della tolleranza, in particolare per questa funzione, o in generale in altri tipi di aritmetica?

Qualche regola empirica o anche meglio, matematicamente, per decidere la tolleranza?

    
posta Graviton 21.09.2018 - 11:31
fonte

4 risposte

2

Il tuo spazio non va all'infinito, quindi sarai in grado di calcolare un angolo tra le linee che determinerà una differenza nel tuo spazio che chiamerai ancora parallelo.

Se visualizzi le linee su uno schermo, potresti fare una differenza che si tradurrà in due linee parallele diverse solo di alcuni pixel.

Il tuo spazio potrebbe essere 25.000 per 25.000 per 25.000, quindi la distanza più lunga è la distanza da un angolo del cubo all'angolo opposto.

Ciò che devi fare è creare due linee a partire da un angolo e terminare nell'altro angolo con una riga mancante per dire 10. Quindi calcolare il prodotto incrociato di quelle linee e il risultato è il tuo obiettivo per le linee parallele .

    
risposta data 21.09.2018 - 11:53
fonte
2

(a) La quantità corretta di arrotondamenti dipende dal dominio del problema. Per esempio. potresti decidere che le linee entro 1 ° l'una dall'altra dovrebbero essere considerate parallele.

(b) La rappresentazione a virgola mobile pone un limite inferiore sull'arrotondamento necessario. La determinazione della propagazione dell'errore è un argomento ampio nel campo dell'analisi numerica .

Tutti i numeri a virgola mobile finiti hanno un predecessore e un numero successore. Questa "dimensione del gradino" tra numeri o "epsilon macchina" dipende dalla grandezza del numero, cioè è più piccola intorno a zero e cresce verso l'infinito positivo e negativo. Ma convenientemente, questo è un errore relativo costante. Per un doppio a 64 bit ci sono 53 bit significativi, che portano ad una dimensione relativa del passo di circa 2 ^ -52 = 2.22E-16 (la macchina epsilon è solitamente definita come la metà di quella).

Supponendo che i valori di input siano il più precisi possibile (ovvero il loro errore relativo è l'epsilon della macchina) è possibile tracciare i calcoli per vedere come si propagano questi errori. Per esempio. per un'aggiunta o sottrazione, è necessario aggiungere gli errori assoluti. Nota che ad es. sottraendo due valori simili potrebbe risultare in un valore che è nell'ordine del suo errore assoluto (cancellazione catastrofica). A volte è possibile riorganizzare i calcoli per evitare questo. Per una moltiplicazione o divisione, puoi aggiungere gli errori relativi.

È possibile utilizzare i risultati dell'analisi per calcolare limiti assoluti e relativi adeguati al runtime.

Come esempio semplicissimo, considera un test per l'uguaglianza di due numeri in virgola mobile a e b, nel presupposto che il loro errore sia epsilon della macchina. Un approccio semplice sarebbe quello di confrontare il float successivo e precedente, cioè prev(a) <= b && b <= next(a) . Se i due numeri hanno errori arbitrari, questo è più difficile ma l'idea è la stessa: derivare limiti di errore assoluti e confrontare se l'area delimitata si sovrappone. Questo può essere fatto convenientemente confrontando la loro differenza, cioè abs(a - b) <= absolute_error .

Per un trattamento completo dei confronti in virgola mobile, leggi link . Quella pagina discute anche quando è più appropriato contare gli ULP (numero di fluttuanti discreti tra due numeri) che trattare con epsilon della macchina.

    
risposta data 21.09.2018 - 12:40
fonte
1

La scelta della giusta tolleranza può essere effettuata solo con la conoscenza del dominio del problema.

Bisogna sapere per cosa sono usate le "linee", cosa rappresentano, quando sono "abbastanza parallele" per il caso d'uso particolare e per cosa viene utilizzato il test di parallelismo. Quindi si può provare a definire una metrica per questo caso d'uso e usarlo per determinare un valore di tolleranza per il prodotto incrociato.

Ad esempio, se il caso d'uso coinvolge solo linee grafiche su uno schermo e "abbastanza parallelo" è definito da "quando le linee sembrano parallele", allora avrai bisogno di una tolleranza piuttosto diversa rispetto, ad esempio, alle linee che rappresentano i confini di alcuni oggetti su una mappa, misurati in metri, chilometri o millimetri, o se le linee rappresentano un oggetto matematico astratto.

Se si intende scrivere una libreria per scopi generici con tale test, che deve essere riutilizzabile per molti casi d'uso diversi, l'unico modo sensato è di fornire un parametro di tolleranza per qualsiasi funzione in cui è richiesto. Si noti che potrebbe risultare che la distanza del prodotto incrociato da zero non è necessariamente la migliore metrica per il caso specifico.

    
risposta data 21.09.2018 - 12:14
fonte
0

Il modo migliore per creare la tua funzione

double CrossProductMagnitude( Line3D l1, Line3d l2 )

e testalo con una varietà di input, finché non decidi tu stesso quanto è piccolo un risultato appropriato per le linee da considerare parallele.

Ad esempio

se l1 è (0,0) a (1000,1000) e l2 è (1,0) a (x, 1000), le linee sono considerate parallele se x = 1002 / 1001,5 / 1001.01 / 1001,000001?

Solo tu puoi decidere che.

    
risposta data 21.09.2018 - 11:56
fonte

Leggi altre domande sui tag