[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Forums >

comp.lang.lisp

is this truncate result ANSI compliant ?

kodifik

10/14/2015 2:23:00 PM

In sbcl cmucl clisp & ecl
* (truncate 4859165753467 4394484)
1105742
226339
....whereas :
* (truncate 4859165753467 4394484.0)
1105742
0.0

gcl & poplog behave more like one would expect
(truncate 4859165753467 4394484.0)
1105742
226339.0
8 Answers

William James

10/14/2015 2:48:00 PM

0

kodifik@gmail.com wrote:

> In sbcl cmucl clisp & ecl
> * (truncate 4859165753467 4394484)
> 1105742
> 226339
> ...whereas :
> * (truncate 4859165753467 4394484.0)
> 1105742
> 0.0
>
> gcl & poplog behave more like one would expect
> (truncate 4859165753467 4394484.0)
> 1105742
> 226339.0

Gauche Scheme:

gosh> (div-and-mod 4859165753467 4394484)
1105742
226339
gosh> (div-and-mod 4859165753467 4394484.0)
1105742.0
226339.0

--
[Jesse Jackson] would spit into the food of white patrons he hated and then
smilingly serve it to them. He did this, he said, "because it gave me
psychological gratification." -- Life Magazine, 1969-11-29

Teemu Likonen

10/14/2015 2:57:00 PM

0

<kodifik@gmail.com> [2015-10-14 07:22:59-07] wrote:

> gcl & poplog behave more like one would expect
> (truncate 4859165753467 4394484.0)
> 1105742
> 226339.0

I'm not sure about compliance but with double-precision floats you get
what you want in SBCL:

CL-USER> (truncate 4859165753467 4394484d0)
1105742
226339.0d0

See also: *READ-DEFAULT-FLOAT-FORMAT*
http://www.lispworks.com/documentation/HyperSpec/Body/v_...

Barry Margolin

10/14/2015 3:37:00 PM

0

In article <87fv1dlcr4.fsf@mithlond.arda>,
Teemu Likonen <tlikonen@iki.fi> wrote:

> <kodifik@gmail.com> [2015-10-14 07:22:59-07] wrote:
>
> > gcl & poplog behave more like one would expect
> > (truncate 4859165753467 4394484.0)
> > 1105742
> > 226339.0
>
> I'm not sure about compliance but with double-precision floats you get
> what you want in SBCL:
>
> CL-USER> (truncate 4859165753467 4394484d0)
> 1105742
> 226339.0d0

This seems like it's compliant.

With single precision, there aren't enough bits to represent
4859165753467 exactly. Assuming a 23-bit mantissa, that's only about 8
decimal digits of precision.

--
Barry Margolin, barmar@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Madhu

10/14/2015 3:50:00 PM

0


* Teemu Likonen <87fv1dlcr4.fsf@mithlond.arda> :
Wrote on Wed, 14 Oct 2015 17:56:47 +0300:

| <kodifik@gmail.com> [2015-10-14 07:22:59-07] wrote:
|
|> gcl & poplog behave more like one would expect
|> (truncate 4859165753467 4394484.0)
|> 1105742
|> 226339.0
|
| I'm not sure about compliance but with double-precision floats you get
| what you want in SBCL:
|
| CL-USER> (truncate 4859165753467 4394484d0)
|
| See also: *READ-DEFAULT-FLOAT-FORMAT*
| http://www.lispworks.com/documentation/HyperSpec/Body/v_...


|> * (truncate 4859165753467 4394484.0)
|> 1105742
|> 0.0

I think mathematically the question of compliance is whether
quotient*divisor+remainder==number, ie.
(TRUNCATE A B) => C, D <==> (= (+ D (* B C)) A)

Lispworks for example gives this: (*read-default-float-format* SINGLE-FLOAT)

* (truncate 4859165753467 4394484.0)
1105742
144296.0

And this is justified because, when you compare single-floats,

(= (+ 144296.0 (* 4394484.0 1105742)) 4859165753467e0)
^^^ remainder

Given the single-float precision, the remainder can be any number from
0.0 below 262144.0. A professor of IEEE floating point could give a
better answer. ---Madhu

kodifik

10/18/2015 5:33:00 PM

0

OK. I understand now.
Thanks everybody.
Didn't know about *READ-DEFAULT-FLOAT-FORMAT*
Great advice.

Günther Thomsen

10/19/2015 10:10:00 PM

0

On Wednesday, October 14, 2015 at 8:50:35 AM UTC-7, Madhu wrote:
> Lispworks for example gives this: (*read-default-float-format* SINGLE-FLOAT)
>
> * (truncate 4859165753467 4394484.0)
> 1105742
> 144296.0
>
> And this is justified because, when you compare single-floats,
>
> (= (+ 144296.0 (* 4394484.0 1105742)) 4859165753467e0)
> ^^^ remainder
>
> Given the single-float precision, the remainder can be any number from
> 0.0 below 262144.0. A professor of IEEE floating point could give a
> better answer. ---Madhu

but, as Barry Margolin hinted at above, 4859165753467e0 is no single float.



In SBCL 1.2.4.debian with
> (truncate 4859165753467 4394484.0)
1105742
0.0

> *read-default-float-format*
SINGLE-FLOAT

and
> (multiple-value-bind (q r) (truncate 4859165753467 4394484) (= (+ r (* q 4394484)) 4859165753467))
T

you'll get
> (multiple-value-bind (q r) (truncate 4859165753467 4394484.0) (= (+ r (* q 4394484)) 4859165753467))
NIL

but that's because
> (float 4859165753467)
4.8591657e12

hence
> (multiple-value-bind (q r) (truncate 4859165753467 4394484.0) (= (+ r (* q 4394484)) (float 4859165753467)))
T


although comparing floats for equality is generally tricky business -- too easy to lose a bit here and there.

Madhu

10/20/2015 2:07:00 AM

0


* Günther Thomsen <550a4002-526a-40b2-a63e-923379608b84@googlegroups.com> :
Wrote on Mon, 19 Oct 2015 15:09:52 -0700 (PDT):

| On Wednesday, October 14, 2015 at 8:50:35 AM UTC-7, Madhu wrote:
|> Lispworks for example gives this: (*read-default-float-format* SINGLE-FLOAT)
|>
|> * (truncate 4859165753467 4394484.0)
|> 1105742
|> 144296.0
|>
|> And this is justified because, when you compare single-floats,
|>
|> (= (+ 144296.0 (* 4394484.0 1105742)) 4859165753467e0)
|> ^^^ remainder
|>
|> Given the single-float precision, the remainder can be any number from
|> 0.0 below 262144.0. A professor of IEEE floating point could give a
|> better answer. ---Madhu
|
| but, as Barry Margolin hinted at above, 4859165753467e0 is no single
| float.

It is a single-float because it has an e0 attached at the end and the
reader will read it as a single float.

<snip>

(TRUNCATE N D) => Q, R <==> (= (+ R (* D Q)) N)

|> (multiple-value-bind (q r) (truncate 4859165753467 4394484) (= (+ r
|> (* q 4394484)) 4859165753467))
| T
|
| you'll get
|> (multiple-value-bind (q r) (truncate 4859165753467 4394484.0) (= (+
|> r (* q 4394484)) 4859165753467))
| NIL

This comes out as NIL from the second rule at "12.1.4.1 Rule of Float
and Rational Contagion", when you are comparing a rational with a float.
However the question of compliance has to check from the other
direction: when your mathematical function (eventually) combines a
rational and float..

| but that's because
|> (float 4859165753467)
| 4.8591657e12

This is the same as 4859165753467e0 in the expression I posted.

| hence
|> (multiple-value-bind (q r) (truncate 4859165753467 4394484.0) (= (+
|> r (* q 4394484)) (float 4859165753467)))
| T

Which is the same expresssion I posted above...

| although comparing floats for equality is generally tricky business --
| too easy to lose a bit here and there.

[I checked my posting again, and did not spot any error, I suggest you
read it again to see exactly what I was trying to explain. Regarding
this comment of yours. I tried to show the numeric range of the bits
that are lost.]---Madhu

Günther Thomsen

10/20/2015 5:06:00 AM

0

On Monday, October 19, 2015 at 7:07:11 PM UTC-7, Madhu wrote:
> * Günther Thomsen <550a4002-526a-40b2-a63e-923379608b84@googlegroups.com> :
> Wrote on Mon, 19 Oct 2015 15:09:52 -0700 (PDT):
>
> | On Wednesday, October 14, 2015 at 8:50:35 AM UTC-7, Madhu wrote:
> |> Lispworks for example gives this: (*read-default-float-format* SINGLE-FLOAT)
> |>
> |> * (truncate 4859165753467 4394484.0)
> |> 1105742
> |> 144296.0
> |>
> |> And this is justified because, when you compare single-floats,
> |>
> |> (= (+ 144296.0 (* 4394484.0 1105742)) 4859165753467e0)
> |> ^^^ remainder
> |>
> |> Given the single-float precision, the remainder can be any number from
> |> 0.0 below 262144.0. A professor of IEEE floating point could give a
> |> better answer. ---Madhu
> |
> | but, as Barry Margolin hinted at above, 4859165753467e0 is no single
> | float.
>
> It is a single-float because it has an e0 attached at the end and the
> reader will read it as a single float.
>
I see now it is. Somehow I expected the compiler to 'upgrade' its type if it doesn't fit, which is clearly is not happening. Thanks for clarifying this.