Raymond Toy wrote:
>>>>>"sjt" == Stephen J Turnbull
<stephen(a)xemacs.org> writes:
>>>>>"Raymond" == Raymond Toy <raymond.toy(a)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))))))