Domanda

Vorrei sapere se posso supporre che stesse operazioni su stessi numeri in virgola mobile a 64 bit fornisce esattamente gli stessi risultati su qualsiasi PC moderno e nei linguaggi di programmazione più comuni? (C ++, Java, C #, ecc). Possiamo supporre, che stiamo operando sui numeri e il risultato è anche un certo numero (senza NaN, INFS e così via).

So che ci sono due standard molto simmilar di calcolo utilizzando numeri in virgola mobile (IEEE 854-1987 e IEEE 754-2008). Tuttavia non so come sia in pratica.

È stato utile?

Soluzione

I moderni processori che implementano virgola mobile 64 bit tipicamente implementare qualcosa che è vicino allo standard IEEE 754-1985, recentemente sostituita dalla norma 754-2008.

Lo standard 754 specifica quale risultato si dovrebbe ottenere da alcune operazioni di base, in particolare addizione, sottrazione, moltiplicazione, divisione, radice quadrata, e negazione. Nella maggior parte dei casi, il risultato numerico è specificato precisamente: Il risultato deve essere il numero rappresentabile che è più vicino alla esatto risultato matematico nella direzione indicata dalla modalità di arrotondamento (più vicino, verso l'infinito, verso zero, o verso l'infinito negativo). Nella modalità "al più vicino", la norma specifica inoltre come i legami sono rotti.

A causa di questo, operazioni che non comportano condizioni di eccezione come troppopieno otterrà gli stessi risultati su diversi processori conformi allo standard.

Tuttavia, esistono diversi problemi che interferiscono con ottenere risultati identici su processori diversi. Uno di questi è che il compilatore è spesso libero implementare sequenze di operazioni a virgola mobile in una varietà di modi. Ad esempio, se si scrive "a = b c + d" in C, in cui tutte le variabili sono dichiarate doppio, il compilatore è libero di calcolare "b c" sia in doppia precisione aritmetica o qualcosa con più vasta o la precisione. Se, per esempio, il processore ha dei registri che possono contenere numeri a virgola mobile estesa precisione e facendo aritmetica in estensione precisione non si assume alcuna più tempo di CPU che fare aritmetica con doppia precisione, un compilatore rischia di generare il codice utilizzando esteso -precisione. Su tale processore, si potrebbe non ottenere gli stessi risultati come si farebbe su un altro processore. Anche se il compilatore fa questo regolarmente, potrebbe non in alcune circostanze, perché i registri sono pieni durante una sequenza complicata, quindi memorizza i risultati intermedi nella memoria temporanea. Quando lo fa, che, si potrebbe scrivere solo il 64-bit doppio piuttosto che il numero esteso precisione. Quindi, una routine che contiene aritmetica in virgola mobile potrebbe dare risultati diversi solo perché è stato compilato con codice diverso, forse inline in un unico luogo, e il compilatore aveva bisogno di registri per qualcos'altro.

Alcuni processori hanno istruzioni per calcolare un multistrato e un componente aggiuntivo in un'istruzione, così "b c + d" potrebbe essere calcolato con alcun arrotondamento intermedio e ottenere un risultato più accurato rispetto a un processore che prima calcola b C e poi aggiunge d.

Il tuo compilatore potrebbe avere interruttori per il controllo del comportamento come questo.

Ci sono alcuni posti in cui il tenore 754-1985 non richiede un risultato unico. Ad esempio, per determinare se si sia verificato underflow (risultato è troppo piccolo per essere rappresentato accuratamente), lo standard permette un'implementazione per rendere la determinazione prima o dopo arrotonda significando (i bit frazione) alla precisione bersaglio. Così alcune implementazioni vi dirà underflow si è verificato quando altre implementazioni non sarà.

Una caratteristica comune nei processori è quella di avere una modalità "quasi IEEE 754" che elimina la difficoltà di trattare con underflow sostituendo lo zero invece di restituire il numero molto piccolo che la norma richiede. Naturalmente, si ottengono numeri diversi quando si esegue in un tale modo che quando si esegue nella modalità più compatibile. La modalità non conforme può essere il default impostata dal compilatore e / o del sistema operativo, per motivi di prestazioni.

Si noti che un'implementazione IEEE 754 non è in genere prevista solo per l'hardware, ma da una combinazione di hardware e software. Il processore può fare il grosso del lavoro ma si basano sul software per gestire alcune eccezioni, impostare determinati modi, e così via.

Quando si sposta al di là delle operazioni aritmetiche di base a cose come seno e coseno, si è molto dipendente dalla biblioteca che si usa. funzioni trascendenti unri generalmente calcolata con approssimazioni accuratamente ingegnerizzati. Le implementazioni sono sviluppati in modo indipendente da vari ingegneri e ottenere risultati diversi tra loro. Su un sistema, la funzione seno può dare risultati accurati all'interno di un ULP (unità di minor precisione) per piccoli argomenti (inferiori pi o così), ma più grandi errori per grandi argomenti. Su un altro sistema, la funzione sin potrebbe dare risultati precisi entro parecchi ULP per tutti gli argomenti. No libreria matematica corrente è noto per produrre risultati in modo corretto arrotondati per tutti gli ingressi. C'è un progetto, crlibm (correttamente arrotondato libm), che ha fatto un buon lavoro verso questo obiettivo, e hanno sviluppato implementazioni per parti significative della libreria matematica che sono correttamente arrotondati e hanno buone prestazioni, ma non tutta la libreria matematica ancora.

In sintesi, se si dispone di un insieme gestibile di calcoli, capire l'implementazione del compilatore, e sono molto attenti, si può fare affidamento sui risultati identici su diversi processori. In caso contrario, ottenendo risultati del tutto identici, non è qualcosa che si può fare affidamento su.

Altri suggerimenti

Se si intende ottenere esattamente lo stesso risultato, quindi la risposta è no.

Si potrebbe anche ottenere risultati diversi per il debug (non ottimizzato) costruisce vs. build di rilascio (ottimizzato) sulla stessa macchina, in alcuni casi, quindi non neppure scontato che i risultati potrebbero essere sempre identici su macchine diverse.

(ciò può accadere ad esempio su un computer con un processore Intel, se l'ottimizzatore mantiene una variabile per un risultato intermedio in un registro, che viene memorizzato nella build non ottimizzata. Poiché registri Intel FPU sono 80 bit, e doppio variabili sono 64 bit, il risultato intermedio vengono memorizzati con maggiore precisione nella build ottimizzata, causando valori diversi nei risultati successivi.).

In pratica, tuttavia, è possibile spesso ottenere gli stessi risultati, ma non si dovrebbe fare affidamento su di esso.

Moderno FPU tutto implementare IEEE754 galleggia in formati singole e doppie, e alcuni in formato esteso. Un certo insieme di operazioni sono supportati (praticamente qualsiasi cosa in math.h), con alcune istruzioni speciali galleggianti intorno là fuori.

supponendo che si sta parlando di applicazione di più operazioni, non credo che si otterrà i numeri esatti. architettura della CPU, l'utilizzo del compilatore, le impostazioni di ottimizzazione cambierà i risultati dei propri calcoli.

se si intende l'ordine esatto delle operazioni (a livello di assieme), Credo sarà comunque ottenere variations.for esempio chip Intel utilizzano precisione estesa (80 bit) internamente, che non può essere il caso per altre CPU. (Non credo precisione estesa ha il compito)

Lo stesso programma C # può mettere in evidenza diversi risultati numerici sullo stesso PC, una volta compilato in modalità debug senza ottimizzazione, la seconda volta compilato in modalità di rilascio con l'ottimizzazione abilitata. Questa è la mia esperienza personale. Noi non consideriamo questo quando abbiamo istituito una suite di test di regressione automatica per uno dei nostri programmi per la prima volta, e sono state completamente sorpreso che un sacco di nostri test non è riuscita senza alcun motivo apparente.

Per C # su x86, vengono utilizzati registri FP 80-bit.

Il C # norma dice che il processore deve operare alla stessa precisione, o maggiore, il tipo stesso (cioè 64 bit nel caso di un 'doppio'). Le promozioni sono ammessi, tranne che per lo stoccaggio. Ciò significa che la gente del posto ei parametri potrebbero essere a maggiore di 64 bit di precisione.

In altre parole, assegnando una variabile membro di una variabile locale potrebbe (e infatti sarà in determinate circostanze) sufficiente dare una disuguaglianza.

Si veda anche: / doppia precisione in modalità debug / rilascio

Per il tipo di dati a 64 bit, so solo di "doppia precisione" / "binary64" dalla IEEE 754 (1985 e 2008 non differiscono molto qui per i casi più comuni) in uso.

Nota:. I tipi di radix definiti in IEEE 854-1987 sono sostituite da IEEE 754-2008 comunque

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top