Scientific Notation Conversion - Scheme
Asked Answered
C

2

5

I am trying to do simple subtraction arithmetic on two very large numbers.

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

When I do this, I get a result of 0.0. I'm expecting an output of:

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

The expanded scientific notation would give me that answer.

183052866407243622723319.24395251 - 183052866407243622723319.00 = .2439521

I would like to represent these numbers as they are, with the decimal numbers in place, as opposed to scientific notation, so I can achieve the desired result. Is there a way of doing this within Scheme? Any help, guidance, or reference would be much appreciated :)

I am using DrRacket for Windows 64bit and R5RS Language.

EDIT

I figured I'd be as specific as possible regarding an example of thearithmetic I'm performing.

arithmetic:

(* 271979577247970257395 0.6180339887) => 1.6809262297150285e+020

When doing this same multiplication in a calculator, the result yeilds => 168092622971502827156.7975214365

When trying to use exact or inexact I get this:

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

I suppose R5RS doesn't support exact/inexact? I looked it up and examples show to use inexact->exact procedure so I did and got this:

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

And just for specificity, I did the opposite:

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

So then I tried using Big Float as someone mentioned:

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

Giving me the same output as exact. All I simply want is to save get the number I would get from a calculator and it seems like a very difficult task! I'm sorry I might sound stupid for not getting this, just keep in mind I'm an extreme amateur in SCHEME. Thanks again for your help! :)

Casern answered 15/4, 2013 at 6:42 Comment(0)
E
4

The problem is that you have more significant digits in the input than Racket uses in its internal representation.

Let us enter the bare numbers:

> 183052866407243622723319.24395251
1.8305286640724363e+23

> 183052866407243622723319.00
1.8305286640724363e+23

Both numbers are thus represented as the same (whole) number internally. This explains why your result was 0.

This behaviour is not limited to Racket. In fact Racket follows the IEEE standard for computing with 64-bit floating-point numbers. You will get same result in other programming languages.

If you need to compute why greater precision you can use bigfloats instead.

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

The result is: (bf #e0.2439525099999997337363311089575290679932)

Note: To use bigfloats make sure you have a recent version of Racket.

Update: In case you wonder why the result wasn't .2439521 the answer is that the result and .2439521 is represented by the same internal bitpattern.

Update:

If you want to turn the result back into a standard floating point, use bigfloat->flonum.

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

This gives the result: 0.24395251

Addendum:

Racket (and Scheme) reads numbers with decimal points as floating point numbers. If you prefix a number with #e it is read as an exact number (that is the resulting value is an exact fraction). You can use this to keep the exact decimals. You exact numbers for your entire computation, and then in the end use exact->inexact to turn the result into a floating point number. Here is your example:

> (exact->inexact 
     (- #e183052866407243622723319.24395251
        #e183052866407243622723319.00))
0.24395251
Electromagnetism answered 15/4, 2013 at 12:8 Comment(6)
Hi, thank you for your prompt response! The bigfloat is not giving me the decimal places I want. I see you are forcefully telling it the decimal places and then doing the subtraction. I am doing arithmetic to retrieve the floating point number. I will update the question so I can show you.Casern
Hi. I added an update, that shows how to turn your result back into a standard floating point number.Electromagnetism
I added an alternative to using bigfloats.Electromagnetism
I understand how big floats work and I appreciate your response. However, the problem is to produce that 183052866407243622723319.24395251 number first. I tried adding #e(* 271979577247970257395 0.6180339887) but #e isn't recognized. :/Casern
#e183052866407243622723319.24395251 The #e is part of the syntax for exact numbers. You can therefore write (* #e1.2 #e3.4), but you can not write #e(* ... since (* does not start a number.Electromagnetism
Thank you! I found a way around this using you and GoZoner's help with the #e. Thanks a bunch again!Casern
C
4

Of course, with Scheme you've got exact numbers:

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

I split x to avoid having the Scheme reader truncate the value. Then:

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

[edit] You need to use exact numbers throughout the computation. That means convert your input to exact and then at the end convert your output in inexact (if desired).

As for your attempt at #e(* 27... 0.6...) - that won't work because the #e applies to numbers, not expressions. use (* #e27... #e0.6...).

> (* #e271979577247970257395 #e0.6180339887)
336185245943005654313595042873/2000000000
Colenecoleopteran answered 15/4, 2013 at 14:50 Comment(3)
You are adding the decimal place explicitly to the large number. Even though this example enlightened me on some things I did not know about the use of inexact and inexact, I'm trying to generate that decimal number through arithmetic. See my update. Thank you for replying though!Casern
I added the decimal explicitly because if I typed it just as a floating point number, then by the time I applied exact is would be too late. Solution to that is to use #e as a prefix to the number itself. Note: see edit above.Colenecoleopteran
Thank you for the update! I found a way around this using your help! Thanks alot GoZoner!Casern

© 2022 - 2024 — McMap. All rights reserved.