5

Sto cercando di eseguire l'aritmetica di sottrazione semplice su due numeri molto grandi.Conversione di notazione scientifica - Schema

(- 1.8305286640724363e+023 (floor 1.8305286640724363e+023)) 

Quando faccio questo, ottengo un risultato di 0.0. Mi aspetto un risultato di:

(- 1.8305286640724363e+023 (floor 1.8305286640724363e+023)) => .2439521 

L'ampliata notazione scientifica mi avrebbe dato quella risposta.

183052866407243622723319,24395251 - 183052866407243622723319,00 = .2439521

Vorrei rappresentare questi numeri così come sono, con i numeri decimali in atto, al contrario di notazione scientifica, in modo da poter ottenere il risultato desiderato. C'è un modo per farlo all'interno di Scheme? Qualsiasi aiuto, guida o riferimento sarebbe molto apprezzato :)

Sto utilizzando DrRacket per Windows a 64 bit e linguaggio R5RS.

EDIT

ho pensato di essere il più specifici possibile in vista di un esempio di thearithmetic sto eseguendo.

aritmetica:

(* 271979577247970257395 0.6180339887) => 1.6809262297150285e+020 

Nel fare questa stessa moltiplicazione in un calcolatore, i yeilds risultato => 168092622971502827156,7975214365

Quando si tenta di utilizzare esatto o inesatto ottengo questo:

(exact (* 271979577247970257395 0.6180339887)) => exact: undefined; 
(inexact (* 271979577247970257395 0.6180339887)) => inexact: undefined; 

Suppongo che R5RS non supporti esatto/inesatto? Ho guardato in su e esempi mostrano di utilizzare inexact-> procedura esatta così ho fatto e ottenuto questo:

(inexact->exact (* 271979577247970257395 0.6180339887)) => 168092622971502854144 

E proprio per la specificità, ho fatto il contrario:

(exact->inexact (* 271979577247970257395 0.6180339887)) => 1.6809262297150285e+020 

Allora ho provato ad utilizzare Big Float come qualcuno menzionato:

(bf-precision 128) 
(bf (* 271979577247970257395 0.6180339887)) => (bf 168092622971502854144) 

Dandomi la stessa uscita esatta. Tutto ciò che voglio è salvare il numero che otterrei da una calcolatrice e sembra un compito molto difficile! Mi dispiace poter sembrare stupido per non averlo capito, ma tieni a mente che sono un dilettante estremo in SCHEME. Grazie ancora per il vostro aiuto! :)

risposta

4

Il problema è che nell'input sono presenti cifre più significative rispetto a in uso nella sua rappresentazione interna.

entriamo numeri nudi:

> 183052866407243622723319.24395251 
1.8305286640724363e+23 

> 183052866407243622723319.00 
1.8305286640724363e+23 

Entrambi i numeri sono quindi rappresentati come lo stesso (intero) Numero internamente. Questo spiega perché il risultato è stato 0.

Questo comportamento non è limitato a Racket. In effetti Racket segue lo standard IEEE per l'elaborazione con numeri a virgola mobile a 64 bit.Otterrete lo stesso risultato in altri linguaggi di programmazione.

Se è necessario calcolare il motivo per cui è più precisa, è possibile utilizzare invece i bigfloats.

(require math/bigfloat) 
(bf-precision 128) ; use 128 bits 
(bf- (bf #e183052866407243622723319.24395251) 
    (bfround (bf #e183052866407243622723319.00))) 

Il risultato è: (bf # e0.2439525099999997337363311089575290679932)

Nota: Per utilizzare bigfloats assicuratevi di avere una versione recente di racchetta.

Aggiornamento: Nel caso in cui ti chiedi perché il risultato non è stato.

Aggiornamento:

Se si desidera attivare il risultato di nuovo in un virgola mobile standard utilizzare bigfloat->flonum.

(bf-precision 256) ; to get more decimal digits correct 
(bigfloat->flonum 
    (bf- (bf #e183052866407243622723319.24395251) 
     (bfround (bf #e183052866407243622723319.00)))) 

Questo dà il risultato: 0,24395251

Addendum:

Racket (e Scheme) legge i numeri con punti decimali come numeri in virgola mobile. Se si prefissa un numero con #e, viene letto come numero esatto (ovvero il valore risultante è una frazione esatta). Puoi usare questo per mantenere i decimali esatti. Esegui i numeri esatti per l'intero calcolo, quindi, alla fine, utilizza exact->inexact per trasformare il risultato in un numero in virgola mobile. Ecco il tuo esempio:

> (exact->inexact 
    (- #e183052866407243622723319.24395251 
     #e183052866407243622723319.00)) 
0.24395251 
+0

Ciao, grazie per la tua pronta risposta! Il bigfloat non mi sta dando i numeri decimali che voglio. Vedo che stai dicendo con forza le cifre decimali e poi esegui la sottrazione. Sto facendo aritmetica per recuperare il numero in virgola mobile. Aggiornerò la domanda in modo che possa mostrarti – Sixers17

+0

Ciao. Ho aggiunto un aggiornamento, che mostra come trasformare il risultato in un numero a virgola mobile standard. – soegaard

+0

Ho aggiunto un'alternativa all'utilizzo di bigfloats. – soegaard

4

Naturalmente, con Scheme hai numeri esatti:

(define x (+ (exact 183052866407243622723319) (exact .24395251))) 
(define y (+ (exact 183052866407243622723319) (exact .0))) 

ho diviso x per evitare di avere il lettore Scheme troncare il valore. Quindi:

> x 
3297587283763054256749149618043779713285/18014398509481984 
> (- x y) 
4394657732528389/18014398509481984 
> (inexact (- x y)) 
0.24395251 

[modifica] È necessario utilizzare numeri esatti durante il calcolo. Ciò significa convertire il tuo input in esatto e poi alla fine convertire il tuo output in inesatto (se lo desideri).

Per quanto riguarda il tuo tentativo di #e(* 27... 0.6...) - che non funzionerà perché il #e si applica ai numeri, non alle espressioni. utilizzare (* #e27... #e0.6...).

> (* #e271979577247970257395 #e0.6180339887) 
336185245943005654313595042873/2000000000 
+0

Stai aggiungendo la cifra decimale in modo esplicito al numero grande.Anche se questo esempio mi ha illuminato su alcune cose che non sapevo sull'uso inesatto e inesatto, sto cercando di generare quel numero decimale attraverso l'aritmetica. Vedi il mio aggiornamento. Grazie per aver risposto! – Sixers17

+0

Ho aggiunto il decimale in modo esplicito perché se l'ho digitato come un numero in virgola mobile, allora quando ho applicato 'exact' è troppo tardi. La soluzione è usare '# e' come prefisso del numero stesso. Nota: vedi modifica sopra. – GoZoner

+0

Grazie per l'aggiornamento! Ho trovato un modo per aggirare questo usando il tuo aiuto! Grazie mille GoZoner! – Sixers17