Dear Marc or Brad,
First - Happy Holidays! :))
A Q:
#e0.3
3/10
(inexact->exact 0.3)
5404319552844595/18014398509481984
#e0.2
1/5
(inexact->exact 0.2)
3602879701896397/18014398509481984
Why the different results? Is there any way to get the #e behavior in a more effective way than (string-append "#e" (number->string n))?
The end goal here is to get decimal arithmetics with precision e.g. (float (* (- 0.3 0.2) 10)) != 0.
Thanks, Mikael
Afficher les réponses par date
On 12/23/2013 07:44 PM, Mikael wrote:
Dear Marc or Brad,
First - Happy Holidays! :))
A Q:
#e0.3
3/10
(inexact->exact 0.3)
5404319552844595/18014398509481984
#e0.2
1/5
(inexact->exact 0.2)
3602879701896397/18014398509481984
Why the different results? Is there any way to get the #e behavior in a more effective way than (string-append "#e" (number->string n))?
I don't think so. inexact->exact works on numbers, the #e notation works on strings. The reader turns "0.3" by default into 5404319552844595/18014398509481984, the closest floating-point 64-bit binary number to 0.3.
I did exactly the trick of appending "#e" to the front of numerical strings for a homework-on-the-web system that I wrote when the students expected to use exact decimal arithmetic.
See:
(- .3 3/10)
0.
(= .3 3/10)
#f
Brad
2013/12/24 Bradley Lucier lucier@math.purdue.edu
On 12/23/2013 07:44 PM, Mikael wrote:
Dear Marc or Brad,
First - Happy Holidays! :))
A Q:
#e0.3
3/10
(inexact->exact 0.3)
5404319552844595/18014398509481984
#e0.2
1/5
(inexact->exact 0.2)
3602879701896397/18014398509481984
Why the different results? Is there any way to get the #e behavior in a more effective way than (string-append "#e" (number->string n))?
I don't think so. inexact->exact works on numbers, the #e notation works on strings. The reader turns "0.3" by default into 5404319552844595/18014398509481984, the closest floating-point 64-bit binary number to 0.3.
Aha so it boils down to be two completely different underlying algorithms - interesting.
Wait, just curious, what is the actual FP 64bit representation of 0.3 and why does it turn out differently like this?
(and (exact->inexact 5404319552844595/18014398509481984) become .3 rather than 0.299[something] or 0.3000[something])
Am having a use case where exact arithmetics are wanted and the precision in decimals is fixed anyhow.
Perhaps using integers and using the lowest digits as decimals makes the most sense?
(as using FP:s seem to lead to weird complexities like this one, automatic disappearance of digits in some cases, and perhaps some potential formatting issue re automatic switching over to scientific notation)
Is a bit unfortunate as integers-as-decimal-numbers isn't too concise, needing to remember that 2345 really means 23.45 and so on.
I did exactly the trick of appending "#e" to the front of numerical
strings for a homework-on-the-web system that I wrote when the students expected to use exact decimal arithmetic.
Mhm.
See:
(- .3 3/10)
(= .3 3/10)
#f
Brad _______________________________________________ Gambit-list mailing list Gambit-list@iro.umontreal.ca https://webmail.iro.umontreal.ca/mailman/listinfo/gambit-list
On Tue, 24 Dec 2013 18:18:03 +0100 Mikael mikael.rcv@gmail.com wrote:
Wait, just curious, what is the actual FP 64bit representation of 0.3 and why does it turn out differently like this?
(and (exact->inexact 5404319552844595/18014398509481984) become .3 rather than 0.299[something] or 0.3000[something])
This may give you a hint:
$ bc obase=2 5404319552844595 10011001100110011001100110011001100110011001100110011 18014398509481984 1000000000000000000000000000000000000000000000000000000 ^D
Or see http://en.wikipedia.org/wiki/Double-precision_floating-point_format
Ah - http://www.binaryconvert.com/result_double.html?decimal=048046051clarifies that
0.3 is represented internally as 2.99999999999999988897769753748E-1 ,
so this is what inexact->exact converts to 5404319552844595/18014398509481984 .
I guess this makes a strong case for representing fixed-point numbers as integers.
2013/12/24 Bakul Shah bakul@bitblocks.com
On Tue, 24 Dec 2013 18:18:03 +0100 Mikael mikael.rcv@gmail.com wrote:
Wait, just curious, what is the actual FP 64bit representation of 0.3 and why does it turn out differently like this?
(and (exact->inexact 5404319552844595/18014398509481984) become .3 rather than 0.299[something] or 0.3000[something])
This may give you a hint:
$ bc obase=2 5404319552844595 10011001100110011001100110011001100110011001100110011 18014398509481984 1000000000000000000000000000000000000000000000000000000 ^D
Or see http://en.wikipedia.org/wiki/Double-precision_floating-point_format
On Dec 24, 2013, at 1:54 PM, Mikael mikael.rcv@gmail.com wrote:
Ah - http://www.binaryconvert.com/result_double.html?decimal=048046051 clarifies that
0.3 is represented internally as 2.99999999999999988897769753748E-1 ,
so this is what inexact->exact converts to 5404319552844595/18014398509481984 .
Hmmm… that’s not the exact decimal representation of the floating point 0.3. In Gambit, to know the exact decimal expansion of an inexact number you can use multiplication by a large power of 10:
(* (expt 10 70) (inexact->exact 0.3))
2999999999999999888977697537484345957636833190917968750000000000000000
Marc
On Tue, 24 Dec 2013 19:54:54 +0100 Mikael mikael.rcv@gmail.com wrote:
Ah - http://www.binaryconvert.com/result_double.html?decimal=048046051clarifi es that
0.3 is represented internally as 2.99999999999999988897769753748E-1 ,
It is /approximated/ as a sum of some (negative) powers of 2 (as that is the best you can do with binary floating point formats).
(- 3/10 (inexact->exact 0.3))
1/90071992547409920
so this is what inexact->exact converts to 5404319552844595/18014398509481984.
I guess this makes a strong case for representing fixed-point numbers as integers.
In general the answer depends what is more important in an application: accuracy, precision, range, exactness, speed, space use, portability etc. Most GPUs for example don't support double precision, while Maxima can use arbitrary precision floats. Financial calculations mostly use (or used to use) decimal arithmetic.
In any case for this you can already use rational numbers in gambit.
(exact? 0.3)
#f
(exact? 3/10)
#t