[Bug: 21.4.19] Bruised floating point numbers from string-to-int

Rodney Sparapani rsparapa at mcw.edu
Thu Apr 6 15:59:57 EDT 2006


Raymond Toy wrote:
>>>>>>"sjt" == Stephen J Turnbull <stephen at xemacs.org> writes:
> 
> 
>>>>>>"Raymond" == Raymond Toy <raymond.toy at ericsson.com> writes:
> 
>     Raymond> If you don't get 1.0, you have a badly broken system, if
>     Raymond> you are using IEEE 754.  0.125 and 0.875 can be
>     Raymond> represented exactly, and so can their sum.  If you don't
>     Raymond> get 1.0, then your reader is broken or your printer.  Or,
>     Raymond> perhaps, + is broken. :-)
> 
>     sjt> But what if I get 1.000?  Where is something broken?  My point is that
>     sjt> a conscientious human presented with the problem
> 
> Oops.  Sorry.  I misinterpreted what you wanted.  The true answer is
> exactly 1, but you wanted it printed out with trailing zeroes.
> 
>     sjt> Yup.  `string-to-int' is an alias for `string-to-number',
>     sjt> which is (ultimately) just a wrapper around the platform's
>     sjt> printf implementation.
>     sjt> What you get is what you get.
> 
>     Raymond> But it is possible to do a better job.
>     Raymond> CMUCL prints "8.18e-1" exactly like that.
> 
>     sjt> Which is *arguably wrong* because you've lost a digit of precision.  I
>     sjt> really don't think *Rodney* can win this way.  Yes, *we* could get
>     sjt> prettier output for the occasional number, but he's working with
>     sjt> tables.
> 
> I think this is a similar confusion on my part.  I meant that the
> result is printed as 0.818 instead of 0.8179999...
> 
>     sjt> Microsoft's apparent do, Unices don't.  Not worth our effort to
>     sjt> replace them, I suggest, unless somebody != me :-) wants to look up
>     sjt> the various algorithms *and* present the rationales, *and* document
>     sjt> the algorithms so people know what to expect, *as well as* update our
> 
> The algorithm for printing floating point numbers accurately is
> available in C on the web, along with a document describing the
> algorithm.  (Look for Dybvig.)
> 
> But I don't use xemacs for floating point work so I have no intentions
> of doing this either. :-)
> 
> Ray
> 
> 

I should have given you an example so you wouldn't have to guess.
Here's what a snippet of the table looks like...
[33]           -6.154E-1   4.865E-1  -1.000E+0   0.000E+0  -1.000E+0
[34]            3.878E-1   4.872E-1   0.000E+0   1.000E+0   0.000E+0
[35]            3.886E-1   4.874E-1   0.000E+0   1.000E+0   0.000E+0
[36]            7.267E-1   4.456E-1   0.000E+0   1.000E+0   1.000E+0
[37]           -2.721E-1   4.450E-1  -1.000E+0   0.000E+0   0.000E+0
[38]           -2.741E-1   4.460E-1  -1.000E+0   0.000E+0   0.000E+0
[39]            3.948E-1   4.888E-1   0.000E+0   1.000E+0   0.000E+0
[40]            3.878E-1   4.872E-1   0.000E+0   1.000E+0   0.000E+0
[41]            3.837E-1   4.862E-1   0.000E+0   1.000E+0   0.000E+0
[42]           -2.662E-1   4.419E-1  -1.000E+0   0.000E+0   0.000E+0
[43]           -6.059E-1   4.886E-1  -1.000E+0   0.000E+0  -1.000E+0
[44]            7.278E-1   4.450E-1   0.000E+0   1.000E+0   1.000E+0
[45]            7.193E-1   4.493E-1   0.000E+0   1.000E+0   1.000E+0
...

After conversion with the function at the end of this message, I get:
[33]           -0.6153999999999999   0.4865    -1.0        0.0 
-1.0
[34]            0.3878     0.4872     0.0        1.0        0.0
[35]            0.3886     0.4874     0.0        1.0        0.0
[36]            0.7267     0.4456     0.0        1.0        1.0
[37]           -0.2721     0.445     -1.0        0.0        0.0
[38]           -0.2741     0.446     -1.0        0.0        0.0
[39]            0.3948     0.4888     0.0        1.0        0.0
[40]            0.3878     0.4872     0.0        1.0        0.0
[41]            0.3837     0.4862     0.0        1.0        0.0
[42]           -0.2662     0.4419    -1.0        0.0        0.0
[43]           -0.6059     0.4886    -1.0        0.0       -1.0
[44]            0.7278     0.445      0.0        1.0        1.0
[45]            0.7193000000000001   0.4493     0.0        1.0        1.0

So, notice that the spacing is ok except for the second column
in row [33] and [45].  Of course, the function handles the spacing,
but that's trivial.  If you uncomment the lines in the function
then we get what we really want, but it requires defensive
programming.  It would be nice if there was a way to avoid the
extra code, since I'm sure it is very fragile:
[33]           -0.61539    0.4865    -1.0        0.0       -1.0
[34]            0.3878     0.4872     0.0        1.0        0.0
[35]            0.3886     0.4874     0.0        1.0        0.0
[36]            0.7267     0.4456     0.0        1.0        1.0
[37]           -0.2721     0.445     -1.0        0.0        0.0
[38]           -0.2741     0.446     -1.0        0.0        0.0
[39]            0.3948     0.4888     0.0        1.0        0.0
[40]            0.3878     0.4872     0.0        1.0        0.0
[41]            0.3837     0.4862     0.0        1.0        0.0
[42]           -0.2662     0.4419    -1.0        0.0        0.0
[43]           -0.6059     0.4886    -1.0        0.0       -1.0
[44]            0.7278     0.445      0.0        1.0        1.0
[45]            0.7193     0.4493     0.0        1.0        1.0

Rodney

(defun ess-bugs-sci-to-round-4-dp ()
     "ESS[BUGS]: round output from +/-0.000E+/-0 to 4 decimal places."
     (interactive)
     (setq buffer-read-only nil)
     (save-excursion (goto-char 0)
     (save-match-data (let ((ess-bugs-replacement-string nil) 

			    (ess-bugs-replacement-9 nil)
			    (ess-bugs-replacement-diff 0))
      (while (search-forward-regexp 
"-?[0-9][.][0-9][0-9][0-9]E[+-][0-9]" nil t)
	    (setq ess-bugs-replacement-string (int-to-string (string-to-int 
(match-string 0))))	
	    (setq ess-bugs-replacement-diff (- (match-end 0) (match-beginning 0)))
;(save-match-data
;    (setq ess-bugs-replacement-9
;	    (string-match "99999999999$" ess-bugs-replacement-string))
;	(if (not ess-bugs-replacement-9)
;	    (setq ess-bugs-replacement-9
;	(string-match "000000000001$" ess-bugs-replacement-string))))
	
;	(if ess-bugs-replacement-9	
;	(setq ess-bugs-replacement-string
;(substring ess-bugs-replacement-string 0 ess-bugs-replacement-9)))

	    (setq ess-bugs-replacement-diff
		(- ess-bugs-replacement-diff (string-width ess-bugs-replacement-string)))

	   (while (> ess-bugs-replacement-diff 0)
		(setq ess-bugs-replacement-string (concat ess-bugs-replacement-string 
" "))
		(setq ess-bugs-replacement-diff (- ess-bugs-replacement-diff 1)))

            (replace-match ess-bugs-replacement-string))))))





More information about the XEmacs-Beta mailing list