Hello all,
I have this string "6192365.43000006" i want to convert it to real
float with exact decimal point
so here is how i am doing it and getting a result i don't want
> (read-from-string "6192365.43000006") => 6192365.5
can anyone help me convert this string to exact float points
many thanks
regards
George Tasso
From: Robert Maas, see http://tinyurl.com/uh3t
Subject: Re: read string to float
Date:
Message-ID: <rem-2008feb26-001@yahoo.com>
> From: ·······@gmail.com
> I have this string "6192365.43000006" i want to convert it to
> real float with exact decimal point
If you mean that you want to find a floating-point value which is
exactly equal to that decimal fraction, that is impossible, because
there is no such floating-point value.
A floating point value is, by definition, an integer divided by a power of two.
(More specifically an integer limited so a fixed number of bits,
but that's irrelevant to the point I'm making here.)
The decimal fraction you gave is *not* exactly equal to *any*
integer divided by *any* power of two.
For an easier case, consider these decimal fractions (not floats):
0.1 0.2 0.3 0.4 0.5 0.6 0.7 0.8 0.9
Only one of those nine decimal fractions is exactly equal to a float,
i.e. an integer divided by a power of two.
Can you figure out which it is?
If you can't figure out the answer in your head, realize that those
decimal fractions as written by mathematicians exactly equal these
common fractions:
1/10 2/10 3/10 4/10 5/10 6/10 7/10 8/10 9/10
=1/5 =2/5 =1/2 =3/5 =4/5
So here's how you can get Lisp to coach you which of those nine
fractions is an exact integer times a power of two: Make a list of
all those fractions, then multiply them all by 2 to see if you get
an integer. Keep multipling by 2 again and again and again and see
if you ever get an integer for any of those.
Here's the code to do that:
(setq vals (list 1/10 2/10 3/10 4/10 5/10 6/10 7/10 8/10 9/10))
;LIsp will remove any common factors of numerator and denominator,
; so you'll get the values from the = line above intermixed with
; the irreducible values from the all/10 line.
(defun vec*2 (l) (mapcar #'(lambda (v) (* 2 v)) l))
;That's the function to multiply every element of a list by2.
(vec*2 vals)
;That does it just once to your list of nine exact rationals.
;Note that one of the nine values doubled is already an integer.
(vec*2 *)
;That does it to the previous result.
;You can repeat this line as often as you want.
;Note that no matter how many times you do this, none of the other
; eight rationals will ever become an integer.
;Thus it's impossible to find any floating-point value whatsoever
; that exactly equals any of the other eight rationals.
Exercise#2: Which of these exact decimal fractions exactly equals
some floating-point value?
0.71 0.72 0.73 0.74 0.75 0.76 0.77 0.78 0.79
Hint: Different vals, but everything else above the same, except
it'll take two steps before one of these becomes an integer.
So at this point you should fully understand why your original
question didn't make any sense.
I suggest if you want to be able to enter decimal-fracction
notation and get an exact value inside the computer, you should
write a function that parses decimal-fraction notation into a
rational, not a float. Here is part of the code you need to include
(doing all work with global variables only during testing the code
one line at a time):
(defun parse-rational-from-decimal-fraction (str)
;(setq str "6192365.43000006") ;Your test data
(setq locdot (position #\. str)) ;Find location of decimal point
(if (position-if-not #'digit-char-p str ;Is there any non-digit
:start (+ 1 locdot)) ; after the decimal point?
(error "Junk after decimal part of number"))
(setq locend (length str))
;If you want to allow junk such as blanks after decimal part,
; rather than error out, then do this instead:
;(setq locend
; (or (position-if-not #'digit-char-p str
; :start (+ 1 locdot))
; (length str)))
(setq pwrten (- locend locdot 1)) ;How many digits to right of decimal point
(setq intstr (format nil "~A~A"
(subseq str 0 locdot)
(subseq str (+ 1 locdot))) ;Removing the decimal point
(setq num (parse-integer intstr)) ; to get an integer for numerator
(setq den (expt 10 pwrten))
(setq rat (/ num den)) ;Note: it'll eliminate common factors
Hey, that's all the code you need! All you need to do is bind all
those temporary variables, and return rat at the end.
You can write a PROG with all those SETQs, and a RETURN statement,
or use one big LET*, with all the SETQs gone, and rat returned implicitly,
your choice.
So once you get parse-rational-from-decimal-fraction working,
you'll be able to get exact values from decimal-fraction-strings
any time you want. Then you never have to mess with floats, exact
rationals will suffice for your needs, so long as you do only
four-function arithmetic.
So back to your original problem: You have exact decimal-fraction
notation, and a way to convert that notation to an exact rational,
but there is no float equal to it. What to do if you want a float
because your instructor in class told you a float was required? You
ask the instructor whether the nearest float is good enough, or
whether you need floats above and below the exactly-correct value.
Depending on the answer to that question, you have different options.
·······@gmail.com writes:
> I have this string "6192365.43000006" i want to convert it to real
> float with exact decimal point
>
> so here is how i am doing it and getting a result i don't want
> > (read-from-string "6192365.43000006") => 6192365.5
>
> can anyone help me convert this string to exact float points
First, this has nothing to do with reading a string.
Second, there is no such thing as "exact floating point". Floating
point numbers are stored in binary, not decimal, and have a fixed
number of binary digits (the length of which varies by the type of the
float an the hardware).
You will get _better_ precision with
(SETQ *READ-DEFAULT-FLOAT-FORMAT* 'DOUBLE-FLOAT)
than the SINGLE-FLOAT setting you are presumably working with.
Or you could use 'LONG-FLOAT.
But that's just a coincidence of these particular numbers. Setting
that value doesn't "ensure exact", it "requests more binary digits
of precision than the default precision". And note that by setting
this you are changing the way all computation is done in your Lisp,
which may have performance impacts on both storage and speed.
Alternatively, if your need is not to generally affect the reader but
to affect this particular situation, you could set the double or long
format for that one number by adding "d0" or "L0" to the end of your
number.
If you literally want exact floats, you want Binary-coded decimal (BCD)
or perhaps something like MACSYMA's "bigfloat" capability (which secretly
maintains ratios of high-precision integers, mostly because it predates
the ratio datatype in CL).
You may find useful information here:
What Every Computer Scientist Should Know About Floating-Point Arithmetic
http://docs.sun.com/source/806-3568/ncg_goldberg.html
And for further reading:
http://en.wikipedia.org/wiki/Floating_point
http://en.wikipedia.org/wiki/Binary-coded_decimal
http://en.wikipedia.org/wiki/Ieee_floating_point
Kent M Pitman <······@nhplace.com> writes:
> ·······@gmail.com writes:
>
>> I have this string "6192365.43000006" i want to convert it to real
>> float with exact decimal point
>>
>> so here is how i am doing it and getting a result i don't want
>> > (read-from-string "6192365.43000006") => 6192365.5
>>
>> can anyone help me convert this string to exact float points
>
> First, this has nothing to do with reading a string.
>
> Second, there is no such thing as "exact floating point". Floating
> point numbers are stored in binary, not decimal, and have a fixed
> number of binary digits (the length of which varies by the type of the
> float an the hardware).
>
> You will get _better_ precision with
> (SETQ *READ-DEFAULT-FLOAT-FORMAT* 'DOUBLE-FLOAT)
> than the SINGLE-FLOAT setting you are presumably working with.
> Or you could use 'LONG-FLOAT.
> But that's just a coincidence of these particular numbers. Setting
> that value doesn't "ensure exact", it "requests more binary digits
> of precision than the default precision". And note that by setting
> this you are changing the way all computation is done in your Lisp,
> which may have performance impacts on both storage and speed.
>
> Alternatively, if your need is not to generally affect the reader but
> to affect this particular situation, you could set the double or long
> format for that one number by adding "d0" or "L0" to the end of your
> number.
>
> If you literally want exact floats, you want Binary-coded decimal (BCD)
> or perhaps something like MACSYMA's "bigfloat" capability (which secretly
> maintains ratios of high-precision integers, mostly because it predates
> the ratio datatype in CL).
>
> You may find useful information here:
>
> What Every Computer Scientist Should Know About Floating-Point Arithmetic
> http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> And for further reading:
>
> http://en.wikipedia.org/wiki/Floating_point
> http://en.wikipedia.org/wiki/Binary-coded_decimal
> http://en.wikipedia.org/wiki/Ieee_floating_point
Another alternative is to implement real real numbers. With CFFI, you
could use this library:
http://www.brics.dk/~barnie/RealLib/
Nicer would be to patch an implementation to make these real numbers
integral part of the Common Lisp type lattice.
--
__Pascal Bourguignon__
PJB> Another alternative is to implement real real numbers. With CFFI, you
PJB> could use this library:
PJB> http://www.brics.dk/~barnie/RealLib/
PJB> Nicer would be to patch an implementation to make these real numbers
PJB> integral part of the Common Lisp type lattice.
i haven't looked inside the lib.. but is this significantly different from
arbitrary-precision long floats of CLISP?
Hi,
> i haven't looked inside the lib.. but is this significantly different from
> arbitrary-precision long floats of CLISP?
Can CLISP exactly represent the square root of 2? RealLib can.
~ Matthias
P� Thu, 28 Feb 2008 17:08:45 +0100, skrev Matthias Benkard
<··········@gmail.com>:
> Hi,
>
>> i haven't looked inside the lib.. but is this significantly different
>> from
>> arbitrary-precision long floats of CLISP?
>
> Can CLISP exactly represent the square root of 2? RealLib can.
>
> ~ Matthias
It can what? (sqrt 2) is a exact representation.
There is no finite number of digits that can represent the whole number.
You can generate arbitrary number of digits or even ask for a specific
digit.
(use binominal expansion in sum form, exponent 1/2, expansion term is k,
error term is k+1, from that determine k and extract the nth digit,
untested)
--------------
John Thingstad
"John Thingstad" <·······@online.no> writes:
> P� Thu, 28 Feb 2008 17:08:45 +0100, skrev Matthias Benkard
> <··········@gmail.com>:
>
>> Hi,
>>
>>> i haven't looked inside the lib.. but is this significantly
>>> different from
>>> arbitrary-precision long floats of CLISP?
>>
>> Can CLISP exactly represent the square root of 2? RealLib can.
>>
>> ~ Matthias
>
> It can what? (sqrt 2) is a exact representation.
It can represent square root of 2 and any other real number. It
doesn't use (sqrt 2) as representation though.
> There is no finite number of digits that can represent the whole number.
This is not totally exact.
There is not enough time in the universe to enumerate all the real
numbers. Actually the universe is finite, so we can consider only a
finite number of real numbers. These real numbers that will be
considered ever is countable and can all be represented in this
universe, by definition. Therefore there are finite number of digits
that can represent any of these whole real numbers.
> You can generate arbitrary number of digits or even ask for a specific
> digit.
> (use binominal expansion in sum form, exponent 1/2, expansion term is
> k, error term is k+1, from that determine k and extract the nth
> digit, untested)
Indeed. That's something like that reallib does.
--
__Pascal Bourguignon__ http://www.informatimago.com/
"This machine is a piece of GAGH! I need dual Opteron 850
processors if I am to do battle with this code!"
On Feb 27, 4:24 pm, Kent M Pitman <······@nhplace.com> wrote:
> ·······@gmail.com writes:
> > I have this string "6192365.43000006" i want to convert it to real
> > float with exact decimal point
>
> > so here is how i am doing it and getting a result i don't want
> > > (read-from-string "6192365.43000006") => 6192365.5
>
> > can anyone help me convert this string to exact float points
>
> First, this has nothing to do with reading a string.
>
> Second, there is no such thing as "exact floating point". Floating
> point numbers are stored in binary, not decimal, and have a fixed
> number of binary digits (the length of which varies by the type of the
> float an the hardware).
>
> You will get _better_ precision with
> (SETQ *READ-DEFAULT-FLOAT-FORMAT* 'DOUBLE-FLOAT)
> than the SINGLE-FLOAT setting you are presumably working with.
> Or you could use 'LONG-FLOAT.
> But that's just a coincidence of these particular numbers. Setting
> that value doesn't "ensure exact", it "requests more binary digits
> of precision than the default precision". And note that by setting
> this you are changing the way all computation is done in your Lisp,
> which may have performance impacts on both storage and speed.
>
> Alternatively, if your need is not to generally affect the reader but
> to affect this particular situation, you could set the double or long
> format for that one number by adding "d0" or "L0" to the end of your
> number.
>
> If you literally want exact floats, you want Binary-coded decimal (BCD)
> or perhaps something like MACSYMA's "bigfloat" capability (which secretly
> maintains ratios of high-precision integers, mostly because it predates
> the ratio datatype in CL).
>
> You may find useful information here:
>
> What Every Computer Scientist Should Know About Floating-Point Arithmetic
> http://docs.sun.com/source/806-3568/ncg_goldberg.html
>
> And for further reading:
>
> http://en.wikipedia.org/wiki/Floating_point
> http://en.wikipedia.org/wiki/Binary-coded_decimal
> http://en.wikipedia.org/wiki/Ieee_floating_point
Thank you Ken alot of reading to be done. Sorry i didn't study enough
maths hence by post.
regards
George
·······@gmail.com wrote:
> Hello all,
>
> I have this string "6192365.43000006" i want to convert it to real
> float with exact decimal point
>
> so here is how i am doing it and getting a result i don't want
>> (read-from-string "6192365.43000006") => 6192365.5
>
> can anyone help me convert this string to exact float points
>
(i) floats
Computer floating point should always come with massive warning signs!
What are usually called "floats" in common lisp are computer floating
point, so "exact float points" is somewhat oxymoronic. See [1] and [2]
Common lisp also defaults to reading decimals as single-precision
floats, which tend to have very few significant bits (bits? Common Lisp
allows for implementations having floats with radix other than 2, but
in practice they'll probably be IEEE binary floating point, since
that's what most hardware supports). But double-precision floats,
at least IEEE ones as used by typical extant lisp implementations, can
come adequately close to representing that number for many purposes,
so the following may be _adequate_ for your purposes...
(let ((*read-default-float-format* 'double-float))
(read-from-string "6192365.43000006"))
- but really, and you'll understand this if you read and understand [1]
and [2] , the double-float that gives you is a bit like the rational
number 6649001751682809/1073741824 , see also lisp functions "rational"
and "rationalize" (and note also the difference between them, too...)
(ii) bignum rationals
Fortunately, common lisps can use (typically slower) rationals, if you
want a more nearly exact representation (though note that "slower").
If you have control of the input string, then you can use common lisp's
standard syntax for rationals to result in a nice representation of
that particular decimal number:
(read-from-string "619236543000006/100000000")
If you want to read decimal-notation numbers as rationals, though, you
may be stuck with implementation-specifics (are there implementations
that do something clever if *read-default-float-format* is set
to 'rational, say? - the spec seems to be written to permit them) or
partially parsing yourself (not that hard for this case) and
constructing a rational.
[1] http://docs.sun.com/source/806-3568/ncg_goldberg.html
[2] http://en.wikipedia.org/wiki/Floating_point
On Feb 27, 4:44 pm, David Golden <············@oceanfree.net> wrote:
> ·······@gmail.com wrote:
> > Hello all,
>
> > I have this string "6192365.43000006" i want to convert it to real
> > float with exact decimal point
>
> > so here is how i am doing it and getting a result i don't want
> >> (read-from-string "6192365.43000006") => 6192365.5
>
> > can anyone help me convert this string to exact float points
>
> (i) floats
>
> Computer floating point should always come with massive warning signs!
>
> What are usually called "floats" in common lisp are computer floating
> point, so "exact float points" is somewhat oxymoronic. See [1] and [2]
>
> Common lisp also defaults to reading decimals as single-precision
> floats, which tend to have very few significant bits (bits? Common Lisp
> allows for implementations having floats with radix other than 2, but
> in practice they'll probably be IEEE binary floating point, since
> that's what most hardware supports). But double-precision floats,
> at least IEEE ones as used by typical extant lisp implementations, can
> come adequately close to representing that number for many purposes,
> so the following may be _adequate_ for your purposes...
>
> (let ((*read-default-float-format* 'double-float))
> (read-from-string "6192365.43000006"))
>
> - but really, and you'll understand this if you read and understand [1]
> and [2] , the double-float that gives you is a bit like the rational
> number 6649001751682809/1073741824 , see also lisp functions "rational"
> and "rationalize" (and note also the difference between them, too...)
>
> (ii) bignum rationals
>
> Fortunately, common lisps can use (typically slower) rationals, if you
> want a more nearly exact representation (though note that "slower").
>
> If you have control of the input string, then you can use common lisp's
> standard syntax for rationals to result in a nice representation of
> that particular decimal number:
>
> (read-from-string "619236543000006/100000000")
>
> If you want to read decimal-notation numbers as rationals, though, you
> may be stuck with implementation-specifics (are there implementations
> that do something clever if *read-default-float-format* is set
> to 'rational, say? - the spec seems to be written to permit them) or
> partially parsing yourself (not that hard for this case) and
> constructing a rational.
>
> [1]http://docs.sun.com/source/806-3568/ncg_goldberg.html
> [2]http://en.wikipedia.org/wiki/Floating_point
Thank you David together with other people's response I do some
reading.
regards George
On Feb 26, 7:53 pm, ·······@gmail.com wrote:
> Hello all,
>
> I have this string "6192365.43000006" i want to convert it to real
> float with exact decimal point
>
> so here is how i am doing it and getting a result i don't want
>
> > (read-from-string "6192365.43000006") => 6192365.5
>
> can anyone help me convert this string to exact float points
>
> many thanks
>
> regards
>
> George Tasso
Try reading the string into double or long float, usually they are the
same
but that depends on your implementation
(read-from-string "6192365.43000006d0")
(read-from-string "6192365.43000006l0")
·······@gmail.com writes:
>
> I have this string "6192365.43000006" i want to convert it to real
> float with exact decimal point
>
> so here is how i am doing it and getting a result i don't want
>> (read-from-string "6192365.43000006") => 6192365.5
>
> can anyone help me convert this string to exact float points
Hi,
There is no such thing as an exact floating point number, but what you
want is maybe to read your number into a double-precision floating point
number instead of a single precision one?
(read-from-string "6192365.43000006"))
=> 6192365.5
(let ((*read-default-float-format* 'double-float))
(read-from-string "6192365.43000006"))
=> 6192365.43000006d0
(read-from-string "6192365.43000006d0"))
=> 6192365.43000006d0
Hope this helps,
Evan
On Feb 27, 3:53 pm, Evan Monroig <·········@obakechan.net> wrote:
> ·······@gmail.com writes:
>
> > I have this string "6192365.43000006" i want to convert it to real
> > float with exact decimal point
>
> > so here is how i am doing it and getting a result i don't want
> >> (read-from-string "6192365.43000006") => 6192365.5
>
> > can anyone help me convert this string to exact float points
>
> Hi,
>
> There is no such thing as an exact floating point number, but what you
> want is maybe to read your number into a double-precision floating point
> number instead of a single precision one?
>
> (read-from-string "6192365.43000006"))
> => 6192365.5
>
> (let ((*read-default-float-format* 'double-float))
> (read-from-string "6192365.43000006"))
> => 6192365.43000006d0
>
> (read-from-string "6192365.43000006d0"))
> => 6192365.43000006d0
>
> Hope this helps,
>
> Evan
exactly what i want thank you.
George