Dichiarazione di non responsabilità: se non sei terribilmente interessato a numeri e processi matematici, questo probabilmente non è niente per te.
Al momento sono un po 'bloccato in un processo di sviluppo di un progetto privato che ho seguito a lungo e penso di aver bisogno di un input perché non posso decidere come farlo al meglio. Purtroppo devo spiegare un po 'il problema.
EDIT: NON riguarda l'implementazione dell'arrotondamento. Questo è già fatto, sia per il float / doppio che per la precisione arbitraria. Puoi presumere di avere una conoscenza sufficiente numeri, modalità di arrotondamento e problemi in virgola mobile, il problema è come progettare gli operatori di arrotondamento in un programma basato su stack.
Sono interessato al problema della riproducibilità nei calcoli numerici. A causa dell'immenso potere (miliardi di operazioni al secondo) e di alcuni problemi delle lingue utilizzate per il numero crunch (C e FORTRAN), le persone non possono controllare ciò che la macchina sta effettivamente facendo al contrario di ciò che la macchina è presumibilmente facendo (Deteoriation di standard di linguaggio come indifferenza a qNaNs e sNaNs, permette di "ottimizzare" a + (b + c) == (a + b) + c, x86 vs MME a virgola mobile, supporto FMA silenzioso ecc. ecc.) . Questa visione è condivisa da William Kahan, il progettista dell'architettura x86 in virgola mobile.
Quindi ho lavorato su un linguaggio basato su stack come FORTH che consente risultati riproducibili. Hai tipi: aggregati (Vector, Matrix, Tensor) e numeri (complessi, reali). Metti due istanze nello stack, esegui un ADD e ottieni la somma risultante. Se gli spazi erano due galleggianti, ottieni un galleggiante. Se gli spazi erano due doppi, si ottiene un doppio. Se i due spazi erano numeri di precisione arbitrari, si ottiene un numero di precisione arbitrario. Lo stesso con i vettori e le matrici.
Il mio problema dolente è l'arrotondamento. Se escludiamo i razionali esatti, dopo la divisione ogni operazione superiore (operazioni algebriche e trascendentali) richiede l'arrotondamento. Esistono due operazioni di arrotondamento già implementate: arrotondamento , impostazione della posizione esatta dell'arrotondamento (arrotondamento: 2.345 utilizzando 0 = > 2 / 2.345 utilizzando -1 = > 2.3) e < em> arrotondamento cifre significative impostando la lunghezza del risultato (arrotondamento per difetto: 2.345 utilizzando 1 = 2 / 2.345 utilizzando 2 = 2.3).
Gli approcci:
-
Un anello per domarli tutti : solo un'impostazione di arrotondamento per tutti i tipi disponibili. Problema: alcune operazioni sono esatte e dovrebbero essere eseguite come tali; numeri arbitrari di precisione offrono l'aggiunta esatta e la moltiplicazione esatta. Se definisco ad es. ADD_EXACT Includo una parola chiave che non è implementata dalla maggior parte dei tipi di dati e sarà quindi un normale ADD e il pericolo è che io (o altri) dimentichi di usare ADD_EXACT quando necessario. Un altro problema è che è opportuno utilizzare diverse modalità di arrotondamento per alcune operazioni: arrotondamento per l'aggiunta e arrotondamento di cifre significative per la moltiplicazione. Ho paura di inondare il programma con interruttori non necessari per impostare la modalità di arrotondamento.
-
Forse altri anelli .... : diverse modalità di arrotondamento impostabili. Consente l'aggiunta e la moltiplicazione in modo indipendente. Problema: molte più possibilità (impostare e recuperare la modalità di arrotondamento, l'arrotondamento e il parametro di arrotondamento). Quante scelte offro? Solo due e rischiando che se ad es. Le FMA non possono essere supportate o molte di più e rischiano di sopraffare il programma con troppa burocrazia di arrotondamento?
L'arrotondamento è un'operazione cruciale e una volta implementata, non può essere modificata facilmente. Questo deve essere risolto nel miglior modo possibile.
Quello di cui ho bisogno è un modello semplice ed elegante e temo di aver lavorato così a lungo su di esso che semplicemente non lo vedo e / o ho bisogno di un piano per trovare la soluzione giusta. L'aiuto è molto apprezzato e aggiornerò questo post per chiarire alcuni aspetti che potrei aver dimenticato.
EDIT: Prestazioni: non è l'obiettivo di progettazione. Non ti aiuta a ottenere una risposta sbagliata incredibilmente veloce. Non ti aiuta se due programmatori su macchine diverse ottengono un risultato diverso o (anche simile) se nessuno sa qual è la risposta giusta (o che anche entrambi sono sbagliati). L'obiettivo del programma è esattamente questo: scoprire quando la precisione IEEE 754R fallirà e trovare indicatori e metodi per convalidare i risultati numerici. Se sai che la doppia precisione e lo strumento ti porteranno alla soluzione, usa C e FORTRAN.