2011-01-05 8 views
5

Ho avuto questo problema a mio avviso i giorni lastfew e sto faticando a esprimere la mia domanda. Tuttavia, penso di aver inchiodato quello che voglio sapere.Qual è il vantaggio di accettare l'inaccuratezza in virgola mobile in C#

Perché C# accetta l'inesattezza utilizzando i punti mobili per memorizzare i dati? E qual è il vantaggio di usarlo su altri metodi?

Ad esempio, Math.Pow(Math.Sqrt(2),2) non è esatto in C#. Esistono linguaggi di programmazione che possono calcolarlo esattamente (ad esempio, Mathematica).

Un argomento che potrei pensare è che il calcolo esattamente è molto più lento poi basta affrontare l'inesattezza, ma Mathematica & Matlab vengono utilizzati per calcolare problemi scientifici giganteschi, quindi trovo difficile credere queste lingue sono davvero in modo significativo più lento di C#.

Allora perché è allora?

PS: Mi dispiace per voi spamming con queste domande, siete stati tutti veramente utile

+0

MatLab viene eseguito in una sandbox Java. Se non credi che MatLab sia più lento, prova a creare un programma in tempo reale in MatLab. Sono stato lì, fatto quello, non è divertente ... :-) –

+0

Ok, ma poi Wolfram Mathematica? Non riuscivo a trovare punti di riferimento su internet dove è rispetto a C# –

+1

Il [CAS] (http://en.wikipedia.org/wiki/Computer_algebra_system) integrato nella calcolatrice TI-89 che praticamente mi ha fatto attraverso l'università corsi di matematica battiti anche i pantaloni della funzionalità matematica incorporata in .NET Framework. Il fatto è semplicemente che sono progettati per casi d'uso completamente diversi. –

risposta

32

Perché C# accetta l'inesattezza utilizzando punti galleggianti per memorizzare i dati?

"C#" non accetta il compromesso tra prestazioni e accuratezza; gli utenti lo accettano o no.

C# ha tre tipi di virgola mobile: float, double e decimal, perché questi tre tipi soddisfano la maggior parte delle esigenze dei programmatori del mondo reale.

float e double sono utili per calcoli "scientifici" in cui una risposta corretta a tre o quattro cifre decimali è sempre abbastanza vicina, poiché è la precisione con cui è stata eseguita la misura originale. Supponi di dividere 10,00 per 3 e di ottenere 3,3333333333333. Poiché la misura originale era probabilmente esatta solo a 0,01, il fatto che il risultato calcolato sia disattivato meno di 0,0000000000004 è irrilevante. Nei calcoli scientifici, non stai rappresentando le quantità esatte conosciute. L'imprecisione nella quindicesima cifra decimale è irrilevante se il valore di misurazione originale era solo preciso alla seconda cifra decimale.

Ovviamente questo non vale per i calcoli finanziari. Gli operandi per un calcolo finanziario sono solitamente precisi a due cifre decimali e rappresentano le quantità esatte. Il decimale va bene per i calcoli "finanziari" perché i risultati delle operazioni decimali sono esatti a condizione che tutti gli ingressi e le uscite possano essere rappresentati esattamente come decimali (e sono tutti in un intervallo ragionevole). I decimali hanno ancora errori di arrotondamento, ovviamente, ma le operazioni esatte sono esattamente quelle che probabilmente vorrai essere esatto quando esegui calcoli finanziari.

E qual è il vantaggio di utilizzarlo su altri metodi?

Si dovrebbe indicare quali altri metodi si desidera confrontare. Esistono moltissime tecniche diverse per eseguire calcoli sui computer.

Ad esempio, Math.Pow (Math.Sqrt (2), 2) non è esatto in C#. Esistono linguaggi di programmazione che possono calcolarlo esattamente (ad esempio, Mathematica).

Siamo chiari su questo punto; Mathematica non "calcola" esattamente la radice 2; il numero è irrazionale, quindi non può essere calcolato esattamente in una quantità limitata di spazio di archiviazione. Invece, ciò che Mathematica fa è che rappresenta i numeri come oggetti che descrivono come il numero è stato prodotto. Se dici "dammi la radice quadrata di due", allora Mathematica assegna essenzialmente un oggetto che significa "l'applicazione dell'operatore della radice quadrata al numero esatto 2". Se poi lo quadrati, ha una logica di scopo speciale che dice "se si piazza qualcosa che era la radice quadrata di qualcos'altro, restituire il valore originale". Mathematica ha oggetti che rappresentano anche vari numeri speciali, come il pi oe, e un enorme corpo di regole su come le varie manipolazioni di quei numeri si combinano insieme.

Fondamentalmente, è un simbolico sistema; manipola i numeri nello stesso modo in cui lo fanno le persone quando fanno matematica a matita e carta. La maggior parte dei programmi per computer manipola numeri come una calcolatrice: esegue immediatamente il calcolo e arrotondalo. Se ciò non è accettabile, dovresti attenersi a un sistema simbolico.

Un argomento che potrei pensare è che il calcolo esattamente è molto più lento poi basta affrontare l'inesattezza, ma Mathematica & Matlab vengono utilizzati per calcolare problemi scientifici giganteschi, quindi trovo difficile credere quelle lingue sono molto più lento di C#.

Non è che siano più lenti, anche se la moltiplicazione di punti mobili è davvero incredibilmente veloce sull'hardware moderno. È che il motore di calcolo simbolico è immensamente complesso. Codifica tutte le regole della matematica di base e ci sono molte di quelle regole! C# non è inteso per essere un motore di calcolo simbolico di livello professionale, è inteso per essere un linguaggio di programmazione generico.

+2

+1 risposta eccellente –

+1

Un sacco di calcolatori scientifici "imbrogliano" mantenendo un paio di cifre in più dietro le quinte e usandole per arrotondare piuttosto che visualizzarle. Considera Google, che ottiene felicemente '' Sqrt (2) ** 2'] (http://www.google.com/search?q=sqrt%282%29%2A%2A2) corretto ... ma per quanto riguarda [ 'sqrt (1,999,999999 millions) ** 2'] (http://www.google.com/search?q=sqrt%281.999999999%29%2A%2A2)? – Brian

+2

+1 Non posso dirvi quanto sia bello vedere un programmatore che capisce e apprezza davvero cifre significative. Ma questa è una risposta davvero fantastica per tanti motivi. –

0

C# e la maggior parte di tutte le altre lingue (ad eccezione di quelli specifici, come Matlab) negozio galleggiante numeri in virgola come campi a dimensione fissa (6 o 8 byte), che portano a inaccuratezza.

+0

Lo so, ma perché usa i numeri in virgola mobile, se ci sono altri modi. –

+0

@Timo In quali altri modi, se stai utilizzando campi a dimensione fissa? La stragrande maggioranza dell'informatica, ad eccezione del calcolo scientifico, non ha bisogno di precisione infinita e può accettare un certo livello di innattezza. –

+0

A causa della velocità di elaborazione e dell'efficienza di archiviazione. Questa è la ragione principale. La maggior parte dei programmi non ha bisogno di precisione in 10 simboli dopo il punto. –

12

Una parola: prestazioni. L'aritmetica a virgola mobile è tipicamente implementata su hardware ed è di molti ordini di grandezza più veloce di altri approcci.

Inoltre, il tuo esempio di MATLAB è falso. MATLAB utilizza l'aritmetica in virgola mobile a precisione doppia proprio come C#.

+1

+1 Non solo le prestazioni, ma il fatto che il compromesso valore-prestazioni non valga la pena nel 99% dei casi. L'unica volta che hai bisogno degli alti livelli di accuratezza che la tua domanda presuppone è se stai facendo calcoli matematici o ingegneristici specializzati. E c'è già un software per questo. –

+0

Ok, ho rimosso l'esempio di MATLAB. Non ero troppo sicuro, ma Mathematica può farlo bene? –

+3

@Timo C'è una differenza tra il calcolo numerico e quello simbolico. La maggior parte dei problemi ingegneristici e scientifici del mondo reale sono meglio serviti da algoritmi numerici e per loro l'aritmetica in virgola mobile è la cosa migliore. Questo è essenzialmente il riformulare ciò che sta dicendo @Cody Gray. –

0

Non penso che sia un problema C#. C# è una lingua generica e ti offre i tipi di dati di base con cui giocare. Se non sei felice con loro sei sempre libero di crearne uno tuo.

Inoltre C# non è colui che accetta l'inesattezza. Il programmatore lo fa. Per l'ampia serie di problemi, l'inaccuratezza è accettabile. Float non dovrebbe essere usato quando è previsto un risultato esatto, ma questa è una decisione per il programmatore e non per il designer del linguaggio.

0

Una ragione è che numeri e formati numerici non sono ambigui e universali. Sì, ci sono errori di arrotondamento, ma sono costanti e prevedibili. Cercare di impostare un formato generale per qualsiasi problema algoritmico non è banale.

2

Per la maggior parte dei problemi di programmazione, l'inaccuratezza non è un problema e i tipi di dati float (o double) sono sufficienti. Molti anni fa, non esistevano "valori in virgola mobile" e il software doveva memorizzare valori come due numeri interi. E la prestazione era un problema (non menzionando errori di programmazione - e scenari wtf - da funzioni di calcolo in virgola mobile fatte su misura). Quindi è stata progettata una convenzione e subito dopo i computer sono stati equipaggiati con FPU s.

Ora, quando utilizzare la FPU per i calcoli o utilizzare altre librerie/programmi matematici (come Mathematica) dipende dal problema. Ad esempio, il calcolo dei vertici in un ambiente 3D preferisce le prestazioni rispetto alla precisione. Ma il software di contabilità è diverso. Sotto questo aspetto, entrambi i problemi differiscono; un software di contabilità non avrà bisogno di calcolare numeri complessi milioni di volte al secondo :) (modifica: o se lo fa, alcuni hardware molto costosi faranno probabilmente parte dell'equazione anche!)

Se sa che vi ritroverete a fare Math.pow (Math.sqrt (2), 2), allora si dovrebbe ripensare il modo in cui si memorizzano entrambi i valori (come il ricalcolo ogni volta). Questo non è un problema con il linguaggio di programmazione, ma più un problema concettuale.

3

Perché C# accetta l'inaccuratezza utilizzando i punti mobili per memorizzare i dati?

In questo modo, il supporto in virgola mobile possono mappare al modo in cui hardware supporta Floating Points, ovvero - è più o meno l'unico modo di sfruttare operazioni in virgola mobile in hardware, che è molto più veloce di una soluzione software. Lo svantaggio è che l'hardware rappresenta i punti in virgola mobile con un numero finito di bit, il che porta a imprecisioni (si noti che l'imprecisione è ben definita).

Altri modi di rappresentare i valori in virgola mobile richiedono una soluzione software, è notevolmente più lento e richiede più spazio. "Chiunque" può implementarlo con ciò che è disponibile in C#, incluso il supporto in virgola mobile nativo per l'hardware disponibile sarebbe abbastanza difficile per "chiunque" se questo non fosse già supportato nella lingua/CLR.

0

C'è un po 'di una spiegazione here per Mathematica

La versione corta è per regolare giorno in giorno in virgola mobile per la matematica, l'hardware può farlo rapidamente con una quantità nota di imprecisione. Quindi, se i tuoi calcoli non dipendono dall'essere più precisi, fallo nel modo più rapido.

Se è necessaria la precisione, il programmatore deve scrivere l'algoritmo in base al grado di precisione richiesto. Quale sarà più lento.

Problemi correlati