From: Jean Louis <bugs@gnu.support>
To: John Yates <john@yates-sheets.org>
Cc: Help Gnu Emacs mailing list <help-gnu-emacs@gnu.org>,
Stefan Monnier <monnier@iro.umontreal.ca>
Subject: Re: What is 0.01 here not 0.01 here 0.009999999999999?
Date: Sat, 3 Apr 2021 02:29:23 +0300 [thread overview]
Message-ID: <YGeo05Ie7JSLFK9B@protected.localdomain> (raw)
In-Reply-To: <CAJnXXojtOvzkCXxaSfL4T+EQS5cRgAOysTuSXo8mvZd2u1bUKg@mail.gmail.com>
* John Yates <john@yates-sheets.org> [2021-04-03 01:05]:
> > Yes, I need arithmetic on imprecise representations... to deliver what
> > I want, and it is doing what I want. `calc-eval' is doing it, and my
> > function is delivering me string that is increased for 0.01 -- well
> > that is what I wanted, and is happening... several times per hour
> > those numbers are increasing, function is working ;-p
>
> This will probably work because each time you increment by an
> approximation of 0.01 you convert back to a decimal representation
> via a path that applies a number of heuristics to guess what value
> you want to see. Having rendered your incremented value as a
> decimal string, when you read it back in you _do not_ recreate
> a bit for bit copy of the earlier sum, but rather a floating point
> number that is the closest approximation possible to the decimal
> number being presented. Put another way, each output / input
> iteration prevents you from accumulating errors.
That is right. I keep the revision number as a string, rather than a
number, as some revisions may have various abbreviations, including
letters or combinations with numbers. But those that are only a number
are or can be automatically increased each time. Though there exists
the unique ID in the database as well to access revisions in order
that are associated to a file.
> If you wanted to support more general arithmetic on your version
> numbers I would advise using scaled integer arithmetic. Assuming
> that you can guarantee the granularity of your version numbers will
> always be 0.01 then you can represent 0.01 as 1 and 11.07 as
> 1107. Then to recover the major version you just divide by 100 and
> to recover the minor version you mod by 100.
From those ideas...
(+ 10.12 0.01) → 10.129999999999999
(/ (1+ 1012) 100.0) → 10.13
(/ (1+ (round (* 10.10 100))) 100.0) → 10.11
(/ (1+ (round (* 10.11 100))) 100.0) → 10.12
(/ (1+ (round (* 10.12 100))) 100.0) → 10.13
Then instead of this:
(defun rcd-vc-increase-decimal-revision-number (nn.nn)
"Increase the floating number NN.NN provided either as number or
string for 0.01."
(if (rcd-vc-revision-is-floating-number-p nn.nn)
(let* ((nn.nn (format "%s" nn.nn))
(nn.nn (format "%.2f" (string-to-number nn.nn)))
(nn.nn (string-to-number nn.nn)))
(format "%.2f" (+ nn.nn 0.01)))
nn.nn))
(defun rcd-vc-increase-decimal-revision-number (nn.nn)
"Increase the floating number NN.NN provided either as number or
string for 0.01."
(if (rcd-vc-revision-is-floating-number-p nn.nn)
(format "%.2f" (/ (1+ (round (* (string-to-number nn.nn) 100))) 100.0))))
Without %.2f this would be:
(rcd-vc-increase-decimal-revision-number "10.09") → "10.1" which
is not what I want.
(rcd-vc-increase-decimal-revision-number "10.00") → "10.01"
(rcd-vc-increase-decimal-revision-number "10.01") → "10.02"
(rcd-vc-increase-decimal-revision-number "10.02") → "10.03"
(rcd-vc-increase-decimal-revision-number "10.03") → "10.04"
(rcd-vc-increase-decimal-revision-number "10.04") → "10.05"
(rcd-vc-increase-decimal-revision-number "10.05") → "10.06"
(rcd-vc-increase-decimal-revision-number "10.06") → "10.07"
(rcd-vc-increase-decimal-revision-number "10.07") → "10.08"
(rcd-vc-increase-decimal-revision-number "10.08") → "10.09"
(rcd-vc-increase-decimal-revision-number "10.09") → "10.10"
(rcd-vc-increase-decimal-revision-number "10.10") → "10.11"
(rcd-vc-increase-decimal-revision-number "10.11") → "10.12"
(rcd-vc-increase-decimal-revision-number "10.12") → "10.13"
(rcd-vc-increase-decimal-revision-number "10.13") → "10.14"
(rcd-vc-increase-decimal-revision-number "10.14") → "10.15"
(rcd-vc-increase-decimal-revision-number "10.15") → "10.16"
(rcd-vc-increase-decimal-revision-number "10.16") → "10.17"
(rcd-vc-increase-decimal-revision-number "10.17") → "10.18"
(rcd-vc-increase-decimal-revision-number "10.18") → "10.19"
(rcd-vc-increase-decimal-revision-number "10.19") → "10.20"
(rcd-vc-increase-decimal-revision-number "10.20") → "10.21"
(rcd-vc-increase-decimal-revision-number "10.21") → "10.22"
(rcd-vc-increase-decimal-revision-number "10.22") → "10.23"
(rcd-vc-increase-decimal-revision-number "10.23") → "10.24"
(rcd-vc-increase-decimal-revision-number "10.24") → "10.25"
(rcd-vc-increase-decimal-revision-number "10.25") → "10.26"
(rcd-vc-increase-decimal-revision-number "10.26") → "10.27"
(rcd-vc-increase-decimal-revision-number "10.27") → "10.28"
(rcd-vc-increase-decimal-revision-number "10.28") → "10.29"
(rcd-vc-increase-decimal-revision-number "10.29") → "10.30"
(rcd-vc-increase-decimal-revision-number "10.30") → "10.31"
(rcd-vc-increase-decimal-revision-number "10.31") → "10.32"
(rcd-vc-increase-decimal-revision-number "10.32") → "10.33"
(rcd-vc-increase-decimal-revision-number "10.33") → "10.34"
(rcd-vc-increase-decimal-revision-number "10.34") → "10.35"
(rcd-vc-increase-decimal-revision-number "10.35") → "10.36"
(rcd-vc-increase-decimal-revision-number "10.36") → "10.37"
(rcd-vc-increase-decimal-revision-number "10.37") → "10.38"
(rcd-vc-increase-decimal-revision-number "10.38") → "10.39"
(rcd-vc-increase-decimal-revision-number "10.39") → "10.40"
(rcd-vc-increase-decimal-revision-number "10.40") → "10.41"
(rcd-vc-increase-decimal-revision-number "10.41") → "10.42"
(rcd-vc-increase-decimal-revision-number "10.42") → "10.43"
(rcd-vc-increase-decimal-revision-number "10.43") → "10.44"
(rcd-vc-increase-decimal-revision-number "10.44") → "10.45"
(rcd-vc-increase-decimal-revision-number "10.45") → "10.46"
(rcd-vc-increase-decimal-revision-number "10.46") → "10.47"
(rcd-vc-increase-decimal-revision-number "10.47") → "10.48"
(rcd-vc-increase-decimal-revision-number "10.48") → "10.49"
(rcd-vc-increase-decimal-revision-number "10.49") → "10.50"
(rcd-vc-increase-decimal-revision-number "10.50") → "10.51"
(rcd-vc-increase-decimal-revision-number "10.51") → "10.52"
(rcd-vc-increase-decimal-revision-number "10.52") → "10.53"
(rcd-vc-increase-decimal-revision-number "10.53") → "10.54"
(rcd-vc-increase-decimal-revision-number "10.54") → "10.55"
(rcd-vc-increase-decimal-revision-number "10.55") → "10.56"
(rcd-vc-increase-decimal-revision-number "10.56") → "10.57"
(rcd-vc-increase-decimal-revision-number "10.57") → "10.58"
(rcd-vc-increase-decimal-revision-number "10.58") → "10.59"
(rcd-vc-increase-decimal-revision-number "10.59") → "10.60"
(rcd-vc-increase-decimal-revision-number "10.60") → "10.61"
(rcd-vc-increase-decimal-revision-number "10.61") → "10.62"
(rcd-vc-increase-decimal-revision-number "10.62") → "10.63"
(rcd-vc-increase-decimal-revision-number "10.63") → "10.64"
(rcd-vc-increase-decimal-revision-number "10.64") → "10.65"
(rcd-vc-increase-decimal-revision-number "10.65") → "10.66"
(rcd-vc-increase-decimal-revision-number "10.66") → "10.67"
(rcd-vc-increase-decimal-revision-number "10.67") → "10.68"
(rcd-vc-increase-decimal-revision-number "10.68") → "10.69"
(rcd-vc-increase-decimal-revision-number "10.69") → "10.70"
(rcd-vc-increase-decimal-revision-number "10.70") → "10.71"
(rcd-vc-increase-decimal-revision-number "10.71") → "10.72"
(rcd-vc-increase-decimal-revision-number "10.71") → "10.72"
> Using 100 is necessary if you want 10.99 + 0.01 to return 11.00.
> If you never expect to handle a carry from your minor version field
> into your major version field then you could scale by a power of
> two (e.g. 128). Then division reduces to right shifting and mod
> to masking (e.g. for 128 that means anding with 127).
Principle is interesting.
Just that I need to keep it as a string in the database, so that
export makes sense without any Lisp, and that shell or `psql' can
export it straight without external formulas, for example, file
can be exported into file system with its revision number without
using calculation of a version number. That is why "10.01" should
be stored in the database as string. Somebody could also
designate it as "v10.01" but that one would not be automatically
incremented. Revision numbers are by free will, and user could
decide if they would be automatically incremented.
Because it is database backed, minimum interaction with the
system is possible. In general, registered files are recorded in
the database on each kill or save of the buffer, or by single
key. I find it handy without any interactions.
--
Jean
Take action in Free Software Foundation campaigns:
https://www.fsf.org/campaigns
Sign an open letter in support of Richard M. Stallman
https://rms-support-letter.github.io/
next prev parent reply other threads:[~2021-04-02 23:29 UTC|newest]
Thread overview: 20+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-04-02 13:42 What is 0.01 here not 0.01 here 0.009999999999999? Jean Louis
2021-04-02 13:56 ` Stefan Monnier
2021-04-02 17:03 ` Jean Louis
2021-04-02 17:41 ` Teemu Likonen
2021-04-02 18:44 ` Jean Louis
2021-04-02 20:46 ` John Yates
2021-04-02 21:19 ` Jean Louis
2021-04-02 22:04 ` John Yates
2021-04-02 23:29 ` Jean Louis [this message]
2021-04-03 4:39 ` Arthur Miller
2021-04-03 5:36 ` Jean Louis
2021-04-03 3:56 ` Arthur Miller
2021-04-03 5:19 ` Jean Louis
2021-04-03 13:54 ` Stefan Monnier
2021-04-02 14:02 ` Eli Zaretskii
2021-04-02 17:07 ` Jean Louis
2021-04-03 4:49 ` Arthur Miller
2021-04-16 20:41 ` Emanuel Berg via Users list for the GNU Emacs text editor
2021-04-17 10:53 ` Jean Louis
2021-04-19 10:51 ` Eric S Fraga
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
List information: https://www.gnu.org/software/emacs/
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=YGeo05Ie7JSLFK9B@protected.localdomain \
--to=bugs@gnu.support \
--cc=help-gnu-emacs@gnu.org \
--cc=john@yates-sheets.org \
--cc=monnier@iro.umontreal.ca \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).