Una cosa che mi piacerebbe vedere sarebbe un riconoscimento del fatto che double
a float
dovrebbe essere considerato come una conversione allargata, mentre float
a double
sta restringendo (*). Questo può sembrare contro-intuitivo, ma considera cosa significano in realtà i tipi:
- 0.1f significa "13.421.773,5 / 134.217.728, più o meno 1 / 268.435.456 o giù di lì".
- 0.1 significa in realtà 3,602,879,701,896,397 / 36,028,797,018,963,968, più o meno 1 / 72,057,594,037,927,936 circa "
Se uno ha un double
che contiene la migliore rappresentazione della quantità "un decimo" e lo converte in float
, il risultato sarà "13.421.773.5 / 134.217.728, più o meno 1 / 268.435.456 o giù di lì", che è una descrizione corretta del valore.
Al contrario, se uno ha un float
che contiene la migliore rappresentazione della quantità "un decimo" e lo converte in double
, il risultato sarà "13.421.773.5 / 134.217.728, più o meno 1 / 72.057.594,037,927,936 o così "- un livello di precisione implicita che è sbagliato per un fattore di oltre 53 milioni.
Sebbene lo standard IEEE-744 richieda l'esecuzione di calcoli a virgola mobile come se ogni numero in virgola mobile rappresenti esattamente la quantità numerica esattamente al centro del suo intervallo, ciò non dovrebbe essere implica che i valori in virgola mobile rappresentano effettivamente quelle quantità numeriche esatte. Piuttosto, il requisito che i valori siano assunti al centro dei loro intervalli deriva da tre fatti: (1) i calcoli devono essere eseguiti come se gli operandi avessero dei valori precisi; (2) ipotesi coerenti e documentate sono più utili di quelle incoerenti o prive di documenti; (3) se si intende fare un'ipotesi coerente, nessun'altra ipotesi coerente può essere migliore di assumere che una quantità rappresenti il centro del suo intervallo.
Per inciso, ricordo che circa 25 anni fa qualcuno ha inventato un pacchetto numerico per C che utilizzava "tipi di intervallo", ciascuno costituito da una coppia di galleggianti a 128 bit; tutti i calcoli sarebbero fatti in modo tale da calcolare il valore minimo e massimo possibile per ogni risultato. Se si eseguiva un grande calcolo iterativo lungo e si otteneva un valore di [12.53401391134 12.53902812673], si poteva essere certi che mentre molte cifre di precisione venivano perse per errori di arrotondamento, il risultato poteva ancora essere ragionevolmente espresso come 12.54 (e non era t veramente 12.9 o 53.2). Sono sorpreso di non aver visto alcun supporto per questi tipi in tutte le lingue mainstream, specialmente dal momento che sembrerebbero un buon abbinamento con le unità matematiche che possono operare su più valori in parallelo.
(*) In pratica, è spesso utile utilizzare valori a doppia precisione per tenere calcoli intermedi quando si lavora con numeri a precisione singola, quindi dover usare un typecast per tutte queste operazioni può essere fastidioso. Le lingue potevano essere d'aiuto avendo un tipo "fuzzy double", che eseguiva i calcoli come double, e poteva essere lanciato liberamente da e verso il singolo; questo sarebbe particolarmente utile se le funzioni che assumono i parametri di tipo double
e return double
potrebbero essere marcate in modo che generino automaticamente un overload che accetta e restituisce invece "fuzzy double".