From: David Bakhash
Subject: bignum overflow ?
Date: 
Message-ID: <cxjzpfoodqa.fsf@hawk.bu.edu>
hi,

I like having bignums at my disposal, but I'm in a situation where I
am forced to take 1/x where x is a very long bignum.  so say I do
this:

(setq y (/ 1.0d0
	   my-bignun))

ACL complains that it can't cast `my-bignum' to a long-float, because
it's too big.  So how to deal?  how do you do arithmatic on bignums?

dave

From: Bruno Haible
Subject: Re: bignum overflow ?
Date: 
Message-ID: <6lghsc$nfr@news.u-bordeaux.fr>
David Bakhash <·····@bu.edu> wrote:
>
> (setq y (/ 1.0d0 my-bignun))
>
> ACL complains that it can't cast `my-bignum' to a long-float, because
> it's too big.  So how to deal?  how do you do arithmatic on bignums?

You could use an implementation better suited for this task. In CLISP
you can do the above computation with long-floats:

  > (/ 1.0L0 (expt 10 60000))
  1.0L-60000

(You cannot do it with double-floats because the IEEE 754 double-floats
give you only an 11 bit exponent. Try evaluating the variables
most-positive-double-float and least-positive-double-float.)

                    Bruno                             http://clisp.cons.org/
From: Markku Laukkanen
Subject: Re: bignum overflow ?
Date: 
Message-ID: <357BB418.DFB0B136@research.nokia.com>
David Bakhash wrote:

> hi,
>
> I like having bignums at my disposal, but I'm in a situation where I
> am forced to take 1/x where x is a very long bignum.  so say I do
> this:
>
> (setq y (/ 1.0d0
>            my-bignun))
>
> ACL complains that it can't cast `my-bignum' to a long-float, because
> it's too big.  So how to deal?  how do you do arithmatic on bignums?
>
> dave

heh heh, no way, the 1.0/very_big_bignum should be +0.0. The bignum range
is infinite (in the memory ranges), the floating point range is not.

    PKY
From: ········@wavehh.hanse.de
Subject: Re: bignum overflow ?
Date: 
Message-ID: <6lglqo$nfu$1@nnrp1.dejanews.com>
In article <···············@hawk.bu.edu>,
  David Bakhash <·····@bu.edu> wrote:
> I like having bignums at my disposal, but I'm in a situation where I
> am forced to take 1/x where x is a very long bignum.  so say I do
> this:
>
> (setq y (/ 1.0d0
> 	   my-bignun))
>
> ACL complains that it can't cast `my-bignum' to a long-float, because
> it's too big.  So how to deal?  how do you do arithmatic on bignums?

Why do you force it to be floating point? If my-bignum is too big to be
represented as a long-float, it's 1/x will be rounded to the smallest number
representable in this particular floating point format, which means it is
plain wrong (the same result for most part of your bignum domain). Some Lisp
do this even silently.

Whatever you want to do with the result, I think you will either have to use
fractions or set y to zero manually if my-bignum is too big.

Martin

-----== Posted via Deja News, The Leader in Internet Discussion ==-----
http://www.dejanews.com/   Now offering spam-free web-based newsreading
From: Chris Reedy
Subject: Re: bignum overflow ?
Date: 
Message-ID: <357D547E.2E4A@mitretek.org>
········@wavehh.hanse.de wrote:
> 
> In article <···············@hawk.bu.edu>,
>   David Bakhash <·····@bu.edu> wrote:
> > I like having bignums at my disposal, but I'm in a situation where I
> > am forced to take 1/x where x is a very long bignum.  so say I do
> > this:
> >
> > (setq y (/ 1.0d0
> >          my-bignun))
> >
> > ACL complains that it can't cast `my-bignum' to a long-float, because
> > it's too big.  So how to deal?  how do you do arithmatic on bignums?
> 
> Why do you force it to be floating point? If my-bignum is too big to be
> represented as a long-float, it's 1/x will be rounded to the smallest number
> representable in this particular floating point format, which means it is
> plain wrong (the same result for most part of your bignum domain). Some Lisp
> do this even silently.
> 
> Whatever you want to do with the result, I think you will either have to use
> fractions or set y to zero manually if my-bignum is too big.
> 
I have a related question: I have a bignum that's too big to convert to
floating point. I would like to print it out as if it were a float,
achieving the effect of:

(format t "~?,?E" (float my-bignum))

Does anyone have code that can do this? Failing that, any ideas on how
to do this?

  Thanks, Chris

-- 
This is an informal message and not an official Mitretek Systems
position.
Dr. Christopher L. Reedy, Mail Stop Z551
Mitretek Systems, 7525 Colshire Drive, McLean, VA 22102-7400
Email: ······@mitretek.org  Phone: (703) 610-1615  FAX: (703) 610-1603
From: Barry Margolin
Subject: Re: bignum overflow ?
Date: 
Message-ID: <2oef1.54$X_4.1168689@cam-news-reader1.bbnplanet.com>
In article <·············@mitretek.org>,
Chris Reedy  <······@mitretek.org> wrote:
>I have a related question: I have a bignum that's too big to convert to
>floating point. I would like to print it out as if it were a float,
>achieving the effect of:
>
>(format t "~?,?E" (float my-bignum))
>
>Does anyone have code that can do this? Failing that, any ideas on how
>to do this?

The following code is untested.  It also needs boundary checking (it will
fail if the number isn't big enough to have the specified number of digits
after the decimal point).  But the basic idea seems right.

(defun format-bignum-like-float (my-bignum decimals)
  "Return a string containing floating point representation of MY-BIGNUM,
with DECIMALS digits after the decimal point."
  (let* ((minus (minusp my-bignum))
         (my-bignum (abs my-bignum))
	 (str (format nil "~D" my-bignum))
         (exponent (1- (length str)))
         (first-char (char str 0))
         (after-point (subseq str 1 decimals))
         (last-digit (char str decimals))
         (after-last-digit (char str (1+ decimals))))
    ;; Round the last digit
    (if (or (char> after-last-digit #\5)
            (and (char= after-last-digit #\5) ;; 5 rounds to even
	         (member last-digit '(#\1 #\3 #\5 #\7 #\9))))
        (setq last-digit (code-char (1+ (char-code last-digit)))))
    (format nil "~:[~;-~]~C.~A~CE~D"
            minus first-char after-point last-digit exponent)))
      

-- 
Barry Margolin, ······@bbnplanet.com
GTE Internetworking, Powered by BBN, Cambridge, MA
*** DON'T SEND TECHNICAL QUESTIONS DIRECTLY TO ME, post them to newsgroups.
From: John Atwood
Subject: Re: bignum overflow ?
Date: 
Message-ID: <6lmf73$r6i$1@news.NERO.NET>
Chris Reedy  <······@mitretek.org> wrote:
>I have a related question: I have a bignum that's too big to convert to
>floating point. I would like to print it out as if it were a float,
>achieving the effect of:
>
>(format t "~?,?E" (float my-bignum))

You can normalize the bignum by finding the number of digits and dividing.
This gives the length: 
     (length (format nil "~a" (abs my-bignum)))
You want to divide by 10^(length-1), so:
     (float (/ my-bignum (expt 10 (1- *))))
print it:
     (format nil "~aE~a" * **)


If you need mor control over the formatting, you can change the (format..
accordingly. There's gotta be a more efficient way of getting the length,
but I don't know it offhand.


John
From: Thomas A. Russ
Subject: Re: bignum overflow ?
Date: 
Message-ID: <ymiu35tgrer.fsf@sevak.isi.edu>
Chris Reedy <······@mitretek.org> writes:
> I have a related question: I have a bignum that's too big to convert to
> floating point. I would like to print it out as if it were a float,
> achieving the effect of:
> 
> (format t "~?,?E" (float my-bignum))
> 
> Does anyone have code that can do this? Failing that, any ideas on how
> to do this?
> 
>   Thanks, Chris

All right, here is an order 0 solution to your problem:


(defun integer-as-float (integer decimal-places &optional (stream t))
  ;; Prints "integer" in exponential format with "decimal-places" digits
  ;;   following the decimal point.  Specially designed to work with
  ;;   bignums.

  (let* ((integer-string (princ-to-string integer))
	 (integer-length (length integer-string)))
    (format stream "~C.~Ae~D"
  	    (char integer-string 0)
            (subseq integer-string 1 (1+ decimal-places))
            integer-length)))

Note:
 (1) this format doesn't properly handle negative numbers.  That is left
     as an exercise for the reader :)
 (2) this format doesn't do any rounding of digit values for
     unprinted values.  For example, calling
       (integer-as-float 3.14159 4)  ==>   3.1415  instead of 3.1416

     Fixing this is also left as an exercise for the reader :)

     This won't be as quite as easy, but using parse-integer to get an
     appropriate leading number and then checking the digit just beyond
     that in the string representation should get you there.

-- 
Thomas A. Russ,  USC/Information Sciences Institute          ···@isi.edu