Perché hai bisogno di galleggiare / raddoppiare?

29

Stavo guardando link e ho riso alla battuta di Jon Skeet che parlava di 0.3 non essendo 0.3. Personalmente non ho mai avuto problemi con i float / decimali / doppi, ma poi ricordo che ho imparato molto presto il 6502 e non avevo mai avuto bisogno di float nella maggior parte dei miei programmi. L'unica volta che l'ho usato era per la grafica e la matematica dove i numeri inaccurati erano ok e l'output era per lo schermo e non per essere archiviato (in un db, file) o dipendente.

La mia domanda è, dove sono i posti in cui normalmente si usano i float / decimali / double? Quindi so di stare attento a questi trucchi. Con i soldi uso i long e i valori di magazzino del centesimo, per la velocità di un oggetto in un gioco aggiungo e divido (o bithift) il valore per sapere se ho bisogno di spostare un pixel o meno. (Ho fatto muovere l'oggetto nei 6502 giorni, non avevamo né divisioni né fluttuanti ma avevamo turni).

Quindi ero per lo più curioso.

    
posta FrustratedWithFormsDesigner 27.06.2011 - 22:15
fonte

12 risposte

28

Perché sono, per la maggior parte degli scopi, più precisi degli interi.

Ora come è? "per la velocità di un oggetto in un gioco ..." questo è un buon esempio per un caso del genere. Supponi di aver bisogno di oggetti molto veloci, come i proiettili. Per essere in grado di descrivere il loro movimento con le variabili di velocità intera, è necessario assicurarsi che le velocità siano nell'intervallo delle variabili intere, il che significa che non si può avere un raster arbitrariamente fine.

Tuttavia, potresti anche voler descrivere alcuni oggetti molto lenti, come la lancetta delle ore di un orologio. Poiché si tratta di circa 6 ordini di grandezza più lenti degli oggetti bullet, i primi ld (10⁶) ≈ 20 bit sono zero, che esclude i tipi short int dall'inizio. Ok, oggi abbiamo long s ovunque, che ci lascia con 12 bit ancora comodi. Ma anche in questo caso, la velocità di clock sarà esatta fino a quattro cifre decimali. Non è un buon orologio ... ma è certamente ok per un gioco. Semplicemente, non vorrai rendere il raster molto più grossolano di quanto sia già.

... che porta a problemi se un giorno ti piacerebbe introdurre un nuovo tipo di oggetto ancora più veloce. Non è rimasto alcun "margine".

Cosa succede se scegliamo un tipo float? Stesse dimensioni di 32 bit, ma ora disponi di 24 bit di precisione completi, per gli oggetti tutti . Ciò significa che l'orologio ha una precisione sufficiente per rimanere sincronizzato fino ai secondi per anni. I proiettili non hanno una precisione maggiore, ma vivono "solo" per frazioni di secondo comunque, quindi sarebbe assolutamente inutile se lo fossero. E non entri in nessun tipo di problema se vuoi descrivere anche oggetti molto più veloci (perché non la velocità della luce? Nessun problema) o molto più lenti. Di certo non avrai bisogno di queste cose in un gioco, ma a volte fai delle simulazioni in fisica.

E con i numeri in virgola mobile, si ottiene sempre la stessa precisione e senza prima dover scegliere con intelligenza un raster non ovvio. Questo è forse il punto più importante, in quanto tali necessità di scelta sono molto soggette a errori.

    
risposta data 28.06.2011 - 01:38
fonte
52

Li usi quando descrivi un valore continuo piuttosto che uno discreto . Non è più complicato da descrivere di quello. Semplicemente non fare l'errore di assumere qualsiasi valore con un punto decimale è continuo. Se cambia tutto in una volta in blocchi, come aggiungere un centesimo, è discreto.

    
risposta data 27.06.2011 - 22:46
fonte
27

Hai davvero due domande qui.

Perché qualcuno ha bisogno di matematica in virgola mobile, comunque?

Come sottolinea Karl Bielefeldt, i numeri in virgola mobile ti permettono di modellare quantità continue - e li trovi dappertutto - non solo nel mondo fisico, ma anche in luoghi come affari e finanza.

Ho usato la matematica in virgola mobile in molte, molte aree della mia carriera di programmatore: chimica, lavorando su AutoCAD e persino scrivendo un simulatore Monte Carlo per fare previsioni finanziarie. In effetti, c'è un ragazzo di nome David E. Shaw che usa tecniche di modellazione scientifica basate su virgola mobile applicate a Wall Street per fare miliardi.

E, naturalmente, c'è la grafica per computer. Mi consulto sullo sviluppo di eye candy per le interfacce utente, e provare a farlo al giorno d'oggi senza una solida conoscenza del punto fluttuante, della trigonometria, del calcolo e dell'algebra lineare, sarebbe come presentarsi a una sparatoria con un coltellino.

Perché qualcuno dovrebbe aver bisogno di un float contro un doppio ?

Con le rappresentazioni standard IEEE 754, un float a 32 bit fornisce circa 7 cifre decimali di precisione ed esponenti nell'intervallo 10 -38 a 10 38 . Un doppio a 64 bit fornisce circa 15 cifre decimali di accuratezza ed esponenti nell'intervallo 10 -307 a 10 307 .

Potrebbe sembrare che un galleggiante sarebbe sufficiente per quello di cui chiunque avrebbe ragionevolmente bisogno, ma non lo è. Ad esempio, molte quantità del mondo reale sono misurate in più di 7 cifre decimali.

Ma più sottilmente, c'è un problema chiamato colloquialmente "errore roundoff". Le rappresentazioni in virgola mobile sono valide solo per valori le cui parti frazionarie hanno un denominatore che è un potere di 2, come 1/2, 1/4, 3/4, ecc. Per rappresentare altre frazioni, come 1/10, si "arrotondano" il valore della frazione binario più vicina, ma è un po 'sbagliato - questo è l' "errore di arrotondamento". Poi, quando fai matematica su quei numeri imprecisi, le inesattezze nei risultati possono essere molto peggiori rispetto a quello che hai iniziato - a volte le percentuali di errore si moltiplicano o si accumulano in modo esponenziale.

Ad ogni modo, più cifre binarie devi lavorare, più la tua rappresentazione binaria arrotondata sarà vicina al numero che stai cercando di rappresentare, quindi il suo errore di arrotondamento sarà minore. Quindi quando fai matematica su di esso, se hai un sacco di cifre su cui lavorare, puoi fare molte più operazioni prima che l'errore di arrotondamento cumulativo si accumuli su dove è un problema.

In realtà, i doppi a 64 bit con le loro 15 cifre decimali non sono sufficienti per molte applicazioni. Stavo usando i numeri in virgola mobile a 80-bit nel 1985, e IEEE ora definisce un tipo a virgola mobile a 128-bit (16-byte), per il quale posso immaginare usi.

    
risposta data 27.06.2011 - 23:50
fonte
20

È un malinteso comune, che ovunque tu abbia a che fare con i soldi, dovresti memorizzare il suo valore come intero (centesimi). Mentre in alcuni casi semplici come lo store online è vero, se hai qualcosa di più avanzato non aiuta molto.

Facciamo un esempio: uno sviluppatore guadagna $ 100.000 all'anno. Qual è il suo stipendio del mese esatto? Usando l'intero ottieni il risultato $ 8333,33 (¢ 833333), che moltiplicato per 12 è $ 99,999,96. Lo hai mantenuto come un integer? No, non è stato così.

Le banche usano sempre valori decimali / interi? Bene, lo fanno per la parte transazionale. Ad esempio, non appena inizi a parlare di investment banking, con l'eccezione di tenere traccia delle transazioni effettive, tutto il resto è fluttuante. Poiché è tutto il codice in-house, non lo vedrai, ma puoi dare il massimo in QuantLib , che è essenzialmente lo stesso (eccetto molto più pulito; -).

Perché usare i galleggianti? Perché usare decimali non aiuta affatto quando si usano funzioni come radice quadrata, logaritmi, potenze con esponenti non interi ecc. E, naturalmente, i float sono molto più veloci dei tipi decimali.

    
risposta data 27.06.2011 - 23:51
fonte
4

Ciò che hai descritto è un ottimo lavoro per situazioni in cui controlli tutti gli input e gli output .

Nella realtà non è così. Dovrai essere in grado di far fronte a sistemi che forniscono i tuoi dati come valori reali con un certo grado di precisione e ti aspetteranno che tu restituisca i dati nello stesso formato. In questi casi incontrerà questi problemi.

In effetti incontrerai questi problemi anche se usi i trucchi che elencherai. Quando si calcola il 17,5% di tasse su un prezzo si ottengono centesimi frazionari, indipendentemente dal fatto che si memorizzi il valore in dollari o centesimi. Devi ottenere l'arrotondamento corretto in quanto l'uomo delle tasse si arrabbia molto se non lo paghi abbastanza. L'utilizzo dei tipi di money corretti (qualunque sia la lingua che stai utilizzando) ti salverà da un mondo di dolore.

    
risposta data 27.06.2011 - 22:25
fonte
3

"Dio ha creato tutti i numeri, tutto il resto è opera dell'uomo."    - Leopold Kronecker (1886).

Per definizione, non hai bisogno di altri tipi di numeri. La completezza di Turing per un linguaggio di programmazione si basa sulle relazioni semplici tra i vari tipi di numeri. Se riesci a lavorare con numeri interi (a / k / a numeri naturali), puoi fare qualsiasi cosa.

La domanda è piuttosto speciosa perché non hai bisogno di loro. Forse vuoi posti dove è conveniente o ottimale o più economico o qualcosa del genere?

    
risposta data 27.06.2011 - 22:24
fonte
2

In una frase, i tipi decimali a virgola mobile incapsulano la conversione da e verso i valori interi (che è tutto il computer sa come gestire a livello binario, non esiste un punto decimale in binario) fornendo una logica, generalmente facile Interfaccia intuitiva per il calcolo dei numeri decimali.

Francamente, dicendo che non hai bisogno di float perché sai come fare la matematica decimale usando interi è come dire che sai fare aritmetica a mano lunga, quindi perché usare una calcolatrice? Quindi conosci il concetto; Bravo. Non significa che devi esercitare questa conoscenza tutto il tempo. Spesso è più veloce, più economico e più comprensibile per un mago non binario per dire semplicemente 3.5 + 4.6 = 8.1 invece di convertire i sig fichi in una quantità intera.

    
risposta data 27.06.2011 - 22:40
fonte
1

Il vantaggio principale dei tipi a virgola mobile è che, da una prospettiva di runtime, due o tre formati (vorrei più lingue supportate con i formati a 80 bit) saranno sufficienti per la maggior parte degli scopi computazionali. Se i linguaggi di programmazione potessero facilmente supportare una famiglia di tipi a virgola fissa, la complessità hardware necessaria per un dato livello di prestazioni sarebbe spesso inferiore con i tipi a virgola fissa rispetto a quella a virgola mobile. Sfortunatamente, fornire tale supporto è tutt'altro che "facile".

Per un linguaggio di programmazione che soddisfi in modo efficiente il 98% delle esigenze numeriche delle applicazioni, dovrebbe includere dozzine di tipi e fornire operazioni di definizione per le centinaia di combinazioni possibili; inoltre, anche se un linguaggio di programmazione avesse un meraviglioso supporto a punto fisso, alcune applicazioni avrebbero comunque bisogno di mantenere una precisione relativa approssimativamente costante su un intervallo sufficientemente ampio da richiedere un virgola mobile. Dato che la matematica a virgola mobile sarà necessaria in alcune occasioni, in qualsiasi caso, i fornitori di hardware si concentrano sulle prestazioni matematiche con due o tre formati in virgola mobile e il codice utilizza questi formati ogni volta che funzionano ragionevolmente bene, in genere otterrà risultati migliori "bang for the buck" rispetto al tentativo di ottimizzare il comportamento della matematica in virgola fissa.

Per inciso, la matematica in virgola fissa era più vantaggiosa con i processori a 8 e 16 bit rispetto a quelli a 32 bit. Su un processore a 8 bit, in una situazione in cui 32 bit non sarebbero sufficienti, un tipo a 40 bit costerebbe solo il 25% di spazio in più e il 25-50% in più del tipo a 32 bit e richiederebbe il 37,5% meno spazio e 37,5-60% di tempo in meno rispetto a un tipo a 64 bit. Su una piattaforma a 32 bit, se un tipo a 32 bit non è sufficiente per qualcosa, ci sono spesso pochi motivi per usare qualcosa di meno di 64 bit. Se un tipo a virgola fissa a 48 bit sarebbe adeguato, un "doppio" a 64 bit funzionerà altrettanto bene del tipo a virgola fissa.

    
risposta data 17.02.2014 - 18:16
fonte
0

In generale, dovresti stare molto attento a usarli. Capire la perdita di precisione che può derivare da calcoli anche semplici è una sfida. Ad esempio, la media di un elenco di numeri come questo è una pessima idea:

double average(List<Double> data) {
  double ans = 0;
  for(Double d : data) {
    ans += d;
  }
  return ans / data.size();
}

Il motivo è che, per gli elenchi sufficientemente grandi, in pratica perdi tutti i punti dati quando ans diventa abbastanza grande (vedi ad esempio questo ). Il problema con questo codice è che per le liste di piccole dimensioni, probabilmente funzionerà solo --- è solo in scala che si interrompe.

Personalmente, penso che dovresti usarli solo quando: a) il calcolo deve essere veramente veloce; b) non ti interessa che il risultato sia probabilmente lontano (a meno che tu non sappia davvero cosa stai facendo).

    
risposta data 27.06.2011 - 23:14
fonte
-1

Un pensiero è che useresti la float o le doppie rappresentazioni quando hai bisogno di gestire valori al di fuori dell'intervallo intero.

Le architetture odierne (all'incirca) hanno un intervallo intero con segno di +/- 2.147.483.647 (32 bit) o +/- 9.223.372.036.854.775,807 (64 bit). Unsigned estende di un fattore 2

IEEE 754 fluttua (approssimativamente) passa da +/- 1,4 × 10 ^ -45 a 3,4 × 10 ^ 38. Double estende tale intervallo a +/- 5 × 10-324 ± 2,225 × 10 ^ -308 con molte condizioni e dettagli omessi qui.

Naturalmente, la ragione più sbalorditiva è che potresti dover rappresentare -0; -)

    
risposta data 27.06.2011 - 22:41
fonte
-1

Il solito motivo è perché sono veloci poiché la JVM utilizza in genere il supporto hardware sottostante (a meno che non si usi strictfp).

Vedi link per ciò che strictfp implica.

    
risposta data 27.06.2011 - 23:47
fonte
-2

Ecco perché abbiamo bisogno di sistemi operativi a 256 bit.

La lunghezza di Plank (la distanza più piccola che puoi misurare) = 10 ^ -35m
L'universo osservabile è di 14 miliardi di parsec attraverso = 10 ^ 25m
Quindi puoi misurare qualsiasi cosa in unità della lunghezza di Plank come numeri interi se hai solo 200 bit di precisione.

    
risposta data 28.06.2011 - 17:39
fonte

Leggi altre domande sui tag