Here's what I propose...
in nparse, use this instead of what's there..
(defun make-number (indata)
;; check first for easy case
(if (null(cdr indata)) ; just an integer
(return-from make-number (readlist (car indata))))
(let* ((data (nreverse indata))
(left (nth 0 data))
(point (nth 1 data))
(right (nth 2 data))
(exponent-marker (car (nth 3 data)))
(exponent-sign (nth 4 data))
(exponent-value(nth 5 data)))
;; say the number is 123.45e6
(setf left (if (null left) 0 (readlist left))) ;; convert (#\1 #\2 #\3)
to 123
(setf right (if (null right)0 (readlist right)));; convert (#\4 #\5) to
45
(setf exponent-sign (cond ((null exponent-sign) 1) ;; either -1 or 1 for
exponent sign
((char= (car exponent-sign) #\-) -1)
(t 1)))
(setf exponent-value (if (null exponent-value)0 (readlist
exponent-value)))
;; convert exponent Maxima was set up to read in any number as a
;; double-float. though commercial macsyma distinguishes between
;; single and double. In this program we compute the exact
;; rational value of a decimal number which is entered in a
;; floating point format. We ask later if the original exponent
;; marker, E, D, S, e, d should be believed. That is, can the
;; number be represented accurately as a double. If not, we
;; convert it to a bigfloat. We may bump up fpprec, the number of
;; binary bits needed to convert the number correctly, if
;; necessary. (3.32 is bits per decimal digit..)
(let* ((fpprec (max fpprec (round(+ (* 3.32 (+(length (nth 0
data))(length (nth 2 data))))
(abs exponent-value)))))
(therational
(* (+ left
(if (= right 0) 0
(* right
(expt 10. (- (length (third data)))))))
(if (= exponent-value 0) 1
(expt 10. (* exponent-value exponent-sign)))))
)
;; at this point we can check the exponent marker and see what makes
sense.
(case exponent-marker
(#\B ($bfloat (tomaxrat therational))) ;it was a bigfloat marker.
do it.
(t ;; (#\E #\D #\e #\d nil) one of the others.
;; now check that the number fits within double range.
;; and that the reader presented no more than 16 decimal digits.
;; and that it is not going to underflow to 0.
(if (and (< -2 (/ therational #.(expt 2 1023)) 2)
(>= 16 (+ (length (nth 0 data))(length (nth 2 data)) ))
(not (< -1 (* therational #.(expt 2 1023)) 1)) )
(* 1.0d0 therational) ; convert to double.
($bfloat (tomaxrat therational))))))))
> -----Original Message-----
> From: maxima-bounces at math.utexas.edu
> [mailto:maxima-bounces at math.utexas.edu] On Behalf Of Richard Fateman
> Sent: Saturday, August 26, 2006 10:27 AM
> To: 'Robert Dodier'
> Cc: 'maxima'
> Subject: Re: [Maxima] realroots
>
> There is an argument to be made that numbers that fall off
> the scale for floats, on input, should automatically be
> parsed into bfloats. That is, 1.0e-500 should become a bfloat.
> This would not avoid the numerical underflow that happens in
> the midst of computation, but it avoids the case of someone
> being surprised when
> rat(1.0e-500) is 0. Mathematica does something like this,
> trying (not completely successfully) to smooth the transition
> between machine and software floats.
>
> Maybe the simplest thing to do is to have every float input
> be read in as a bigfloat, and then if it looks like it fits
> into a double float and that's what the user requested (e.g.
> 1.0d3, not 1.0b3), convert it down. Maybe $fpprec would have
> to be set at least at some minimum.
>
> The place to change would be in nparse.lisp near line 460.
>
> RJF
>
> _______________________________________________
> Maxima mailing list
> Maxima at math.utexas.edu
> http://www.math.utexas.edu/mailman/listinfo/maxima
>