From mboxrd@z Thu Jan 1 00:00:00 1970 Path: news.gmane.io!.POSTED.blaine.gmane.org!not-for-mail From: Arthur Miller Newsgroups: gmane.emacs.help Subject: Re: What is 0.01 here not 0.01 here 0.009999999999999? Date: Sat, 03 Apr 2021 06:39:52 +0200 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=gb2312 Content-Transfer-Encoding: quoted-printable Injection-Info: ciao.gmane.io; posting-host="blaine.gmane.org:116.202.254.214"; logging-data="23064"; mail-complaints-to="usenet@ciao.gmane.io" User-Agent: Gnus/5.13 (Gnus v5.13) Emacs/27.1 (windows-nt) Cc: Help Gnu Emacs mailing list , Stefan Monnier To: John Yates Original-X-From: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Sat Apr 03 06:40:40 2021 Return-path: Envelope-to: geh-help-gnu-emacs@m.gmane-mx.org Original-Received: from lists.gnu.org ([209.51.188.17]) by ciao.gmane.io with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.92) (envelope-from ) id 1lSY5Q-0005tH-2t for geh-help-gnu-emacs@m.gmane-mx.org; Sat, 03 Apr 2021 06:40:40 +0200 Original-Received: from localhost ([::1]:42266 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1lSY5P-0003Cm-4z for geh-help-gnu-emacs@m.gmane-mx.org; Sat, 03 Apr 2021 00:40:39 -0400 Original-Received: from eggs.gnu.org ([2001:470:142:3::10]:60882) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lSY4m-0003Be-Uu for help-gnu-emacs@gnu.org; Sat, 03 Apr 2021 00:40:01 -0400 Original-Received: from mail-oln040092074048.outbound.protection.outlook.com ([40.92.74.48]:14307 helo=EUR04-DB3-obe.outbound.protection.outlook.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1lSY4j-0002an-2W for help-gnu-emacs@gnu.org; Sat, 03 Apr 2021 00:40:00 -0400 ARC-Seal: i=1; a=rsa-sha256; s=arcselector9901; d=microsoft.com; cv=none; b=OJbDXrthq/lODme+Y1NqIErMRJUbMsrR26TSZ+em8Gfa/4rK8QuxABBf/GOLVJiSWTaChPuERVvzzJeJW7Ttoaqz9VaSuW7DAgeoipsjj7Dr+ODlnkqNMtfNKiozHfVZq0la1Kr9Rhb1UFuCX1dh3vTCsEtxwZA0eAIcPzPn+1dLJ/LKvYW0/khh6s++k8nbowa3pivpqtV/zXuQYfYcKZM28DmwG/8GmMNkbC6NgCibHwwAPWPF8SzCN+HovCVvRveYWT+Mgy14BfiaJAGXT62hHow8GnOh/c0kEjkTi+TIJAN8ynybvjGtWkDqgKE9prKgvU3bnPWL98dmXTspiA== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=microsoft.com; s=arcselector9901; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XNXqSdlsHK7pF0xsoLurfB8zUex9JO4ml2qTMshrQ7Y=; b=U19rksK8lqdbZGCDrCLOlfAItykWFHBECIDJxYAfv5e9HAAAqwGQdCDq8G+2lu+77zPSWpftQKC49/+MafjUHMBhVgfBf44//Mtk3SVQ/J2yc9O/9CbU+mgM7WdabNX+g+9D1WI8wlEKDt5ExjCAiUI6uamK0PLukoE35oGt20h6mu2GKv4MDitIlrlJOrmxIT7AEItwEy+qYYnWfa9EoVahklpMGA4obUrEQS7ai/eMae6n+C4vWDA3GfSPU+dh3NwAXlEQe6COZ1kwoVeu7RBblJNg4U2GYH+Dw5jSKj9cMgI68xjL1pLR5MIOXYS1gjJCMV1KjPb6Y38u32Ib4g== ARC-Authentication-Results: i=1; mx.microsoft.com 1; spf=none; dmarc=none; dkim=none; arc=none DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=live.com; s=selector1; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version:X-MS-Exchange-SenderADCheck; bh=XNXqSdlsHK7pF0xsoLurfB8zUex9JO4ml2qTMshrQ7Y=; b=kTBUD80dpeWjTVjkgCoHrETb7D4Y7W7p71W0KdEoCSqLGYZw1Lh6Z5HMEfrJyWSAYau7ybdHj6dUJFCF8UKHli8Vq8da8QCTcC3p2wMEjOjzgZcs/lo2Pd806kgXEizNkXy1hgmnbO5yrEOzbi/QKWvDdtkPF6U3cbdqw/2Vg/JEuZ3pimqO+SWnctj+M119woYBqD5eYJTF9Z7+LzlixV/6cVXw70IggTT98IAaIktz5M9IQ86ozIju2JAbVtpjSOgfaB3CKP+e5UzzPFioctz5LV1iFDzRtGE511otF95t3IRYypuNaXDAL8c6LPSkfBGrnNcIofgAFzvXwa3kFw== Original-Received: from DB3EUR04FT003.eop-eur04.prod.protection.outlook.com (2a01:111:e400:7e0c::4b) by DB3EUR04HT161.eop-eur04.prod.protection.outlook.com (2a01:111:e400:7e0c::442) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3999.28; Sat, 3 Apr 2021 04:39:54 +0000 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com (2a01:111:e400:7e0c::51) by DB3EUR04FT003.mail.protection.outlook.com (2a01:111:e400:7e0c::171) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.3999.28 via Frontend Transport; Sat, 3 Apr 2021 04:39:54 +0000 X-IncomingTopHeaderMarker: OriginalChecksum:117DA49F71B96DAA1A3F8598028F3A9F71B016C8A46DC94F78AE32BF182E1755; UpperCasedChecksum:49087142EEE62D3599DF2F49593749D2663242A6551D2586384FFF5250546F95; SizeAsReceived:9087; Count:47 Original-Received: from AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::2103:e705:bc0c:5a8b]) by AM9PR09MB4977.eurprd09.prod.outlook.com ([fe80::2103:e705:bc0c:5a8b%6]) with mapi id 15.20.3999.032; Sat, 3 Apr 2021 04:39:54 +0000 In-Reply-To: (Jean Louis's message of "Sat, 3 Apr 2021 02:29:23 +0300") X-TMN: [fZX9rvqFWCyXwrUL+Bl0Itx3IdTMBQJ8] X-ClientProxiedBy: AM5PR0701CA0023.eurprd07.prod.outlook.com (2603:10a6:203:51::33) To AM9PR09MB4977.eurprd09.prod.outlook.com (2603:10a6:20b:304::20) X-Microsoft-Original-Message-ID: <82a6qgugkn.fsf@live.com> X-MS-Exchange-MessageSentRepresentingType: 1 Original-Received: from HP-Laptop.homepc (81.232.177.30) by AM5PR0701CA0023.eurprd07.prod.outlook.com (2603:10a6:203:51::33) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id 15.20.4020.8 via Frontend Transport; Sat, 3 Apr 2021 04:39:53 +0000 X-MS-PublicTrafficType: Email X-IncomingHeaderCount: 47 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-Correlation-Id: 4cf8f967-3888-4542-1f9a-08d8f65a8690 X-MS-TrafficTypeDiagnostic: DB3EUR04HT161: X-Microsoft-Antispam: BCL:0; X-Microsoft-Antispam-Message-Info: t+b8+HEGmeevAYKC7aIaVLgtwlya9GvQ7//nQqe96OhK8fy8s734zYBdkcX47KgA7DQ+krlK+zZtAZu5utTQO0pZoMyp7TgIjYrQQQ5UNIXX6nhrprRBoweKKZTh21brHE6NkYVL2iCRB0KufW8ImKx8FDpSWJjcJEohVTdGo+ncBUyZXf84kuBEWcBRdW7wkhBrENFtap3DktIX66MLSQZqBxrhvHVfJP2U5AOupfPDPfNALQfMZAQWjTAJmSooQaM3PuP8CkU52x7tb1nqUrKOM1Xd5NwmszsvxcyKNEdVf00QXNe3aqWVzH0WQOVv/UgkN5GpH/4cbuf5snzVmEbiEdoqoCNtp+ycgGnYZtuDKefbh8bhPcdaCPXkPuSNbeq4YnJw2IBLbLidC/oMQA== X-MS-Exchange-AntiSpam-MessageData: /DAX1+x1IX9cfyMwhMcUnK+i5NuoRnoWh9b5qM/gWnGVFVY22Uu5UrVcvHfz09sE6ZaOgOLNI4K1Gwvrn9sNCc5MHLN08Da8wmZCTtfp5dXXaCQzbpje0SutDrPIdaFYxKKiaEOaC/yrMfBRlpFG6w== X-OriginatorOrg: live.com X-MS-Exchange-CrossTenant-Network-Message-Id: 4cf8f967-3888-4542-1f9a-08d8f65a8690 X-MS-Exchange-CrossTenant-OriginalArrivalTime: 03 Apr 2021 04:39:54.0953 (UTC) X-MS-Exchange-CrossTenant-FromEntityHeader: Hosted X-MS-Exchange-CrossTenant-Id: 84df9e7f-e9f6-40af-b435-aaaaaaaaaaaa X-MS-Exchange-CrossTenant-AuthSource: DB3EUR04FT003.eop-eur04.prod.protection.outlook.com X-MS-Exchange-CrossTenant-AuthAs: Anonymous X-MS-Exchange-CrossTenant-FromEntityHeader: Internet X-MS-Exchange-CrossTenant-RMS-PersistedConsumerOrg: 00000000-0000-0000-0000-000000000000 X-MS-Exchange-Transport-CrossTenantHeadersStamped: DB3EUR04HT161 Received-SPF: pass client-ip=40.92.74.48; envelope-from=arthur.miller@live.com; helo=EUR04-DB3-obe.outbound.protection.outlook.com X-Spam_score_int: -20 X-Spam_score: -2.1 X-Spam_bar: -- X-Spam_report: (-2.1 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, FREEMAIL_FROM=0.001, MSGID_FROM_MTA_HEADER=0.001, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-0.001, SPF_HELO_PASS=-0.001, SPF_PASS=-0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: help-gnu-emacs@gnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: Users list for the GNU Emacs text editor List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: help-gnu-emacs-bounces+geh-help-gnu-emacs=m.gmane-mx.org@gnu.org Original-Sender: "help-gnu-emacs" Xref: news.gmane.io gmane.emacs.help:128833 Archived-At: Jean Louis writes: > * John Yates [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 >>=20 >> 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) =A1=FA 10.129999999999999 > (/ (1+ 1012) 100.0) =A1=FA 10.13 > (/ (1+ (round (* 10.10 100))) 100.0) =A1=FA 10.11 > (/ (1+ (round (* 10.11 100))) 100.0) =A1=FA 10.12 > (/ (1+ (round (* 10.12 100))) 100.0) =A1=FA 10.13 > =20 > 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") =A1=FA "10.1" which > is not what I want. > > (rcd-vc-increase-decimal-revision-number "10.00") =A1=FA "10.01" > (rcd-vc-increase-decimal-revision-number "10.01") =A1=FA "10.02" > (rcd-vc-increase-decimal-revision-number "10.02") =A1=FA "10.03" > (rcd-vc-increase-decimal-revision-number "10.03") =A1=FA "10.04" > (rcd-vc-increase-decimal-revision-number "10.04") =A1=FA "10.05" > (rcd-vc-increase-decimal-revision-number "10.05") =A1=FA "10.06" > (rcd-vc-increase-decimal-revision-number "10.06") =A1=FA "10.07" > (rcd-vc-increase-decimal-revision-number "10.07") =A1=FA "10.08" > (rcd-vc-increase-decimal-revision-number "10.08") =A1=FA "10.09" > (rcd-vc-increase-decimal-revision-number "10.09") =A1=FA "10.10" > (rcd-vc-increase-decimal-revision-number "10.10") =A1=FA "10.11" > (rcd-vc-increase-decimal-revision-number "10.11") =A1=FA "10.12" > (rcd-vc-increase-decimal-revision-number "10.12") =A1=FA "10.13" > (rcd-vc-increase-decimal-revision-number "10.13") =A1=FA "10.14" > (rcd-vc-increase-decimal-revision-number "10.14") =A1=FA "10.15" > (rcd-vc-increase-decimal-revision-number "10.15") =A1=FA "10.16" > (rcd-vc-increase-decimal-revision-number "10.16") =A1=FA "10.17" > (rcd-vc-increase-decimal-revision-number "10.17") =A1=FA "10.18" > (rcd-vc-increase-decimal-revision-number "10.18") =A1=FA "10.19" > (rcd-vc-increase-decimal-revision-number "10.19") =A1=FA "10.20" > (rcd-vc-increase-decimal-revision-number "10.20") =A1=FA "10.21" > (rcd-vc-increase-decimal-revision-number "10.21") =A1=FA "10.22" > (rcd-vc-increase-decimal-revision-number "10.22") =A1=FA "10.23" > (rcd-vc-increase-decimal-revision-number "10.23") =A1=FA "10.24" > (rcd-vc-increase-decimal-revision-number "10.24") =A1=FA "10.25" > (rcd-vc-increase-decimal-revision-number "10.25") =A1=FA "10.26" > (rcd-vc-increase-decimal-revision-number "10.26") =A1=FA "10.27" > (rcd-vc-increase-decimal-revision-number "10.27") =A1=FA "10.28" > (rcd-vc-increase-decimal-revision-number "10.28") =A1=FA "10.29" > (rcd-vc-increase-decimal-revision-number "10.29") =A1=FA "10.30" > (rcd-vc-increase-decimal-revision-number "10.30") =A1=FA "10.31" > (rcd-vc-increase-decimal-revision-number "10.31") =A1=FA "10.32" > (rcd-vc-increase-decimal-revision-number "10.32") =A1=FA "10.33" > (rcd-vc-increase-decimal-revision-number "10.33") =A1=FA "10.34" > (rcd-vc-increase-decimal-revision-number "10.34") =A1=FA "10.35" > (rcd-vc-increase-decimal-revision-number "10.35") =A1=FA "10.36" > (rcd-vc-increase-decimal-revision-number "10.36") =A1=FA "10.37" > (rcd-vc-increase-decimal-revision-number "10.37") =A1=FA "10.38" > (rcd-vc-increase-decimal-revision-number "10.38") =A1=FA "10.39" > (rcd-vc-increase-decimal-revision-number "10.39") =A1=FA "10.40" > (rcd-vc-increase-decimal-revision-number "10.40") =A1=FA "10.41" > (rcd-vc-increase-decimal-revision-number "10.41") =A1=FA "10.42" > (rcd-vc-increase-decimal-revision-number "10.42") =A1=FA "10.43" > (rcd-vc-increase-decimal-revision-number "10.43") =A1=FA "10.44" > (rcd-vc-increase-decimal-revision-number "10.44") =A1=FA "10.45" > (rcd-vc-increase-decimal-revision-number "10.45") =A1=FA "10.46" > (rcd-vc-increase-decimal-revision-number "10.46") =A1=FA "10.47" > (rcd-vc-increase-decimal-revision-number "10.47") =A1=FA "10.48" > (rcd-vc-increase-decimal-revision-number "10.48") =A1=FA "10.49" > (rcd-vc-increase-decimal-revision-number "10.49") =A1=FA "10.50" > (rcd-vc-increase-decimal-revision-number "10.50") =A1=FA "10.51" > (rcd-vc-increase-decimal-revision-number "10.51") =A1=FA "10.52" > (rcd-vc-increase-decimal-revision-number "10.52") =A1=FA "10.53" > (rcd-vc-increase-decimal-revision-number "10.53") =A1=FA "10.54" > (rcd-vc-increase-decimal-revision-number "10.54") =A1=FA "10.55" > (rcd-vc-increase-decimal-revision-number "10.55") =A1=FA "10.56" > (rcd-vc-increase-decimal-revision-number "10.56") =A1=FA "10.57" > (rcd-vc-increase-decimal-revision-number "10.57") =A1=FA "10.58" > (rcd-vc-increase-decimal-revision-number "10.58") =A1=FA "10.59" > (rcd-vc-increase-decimal-revision-number "10.59") =A1=FA "10.60" > (rcd-vc-increase-decimal-revision-number "10.60") =A1=FA "10.61" > (rcd-vc-increase-decimal-revision-number "10.61") =A1=FA "10.62" > (rcd-vc-increase-decimal-revision-number "10.62") =A1=FA "10.63" > (rcd-vc-increase-decimal-revision-number "10.63") =A1=FA "10.64" > (rcd-vc-increase-decimal-revision-number "10.64") =A1=FA "10.65" > (rcd-vc-increase-decimal-revision-number "10.65") =A1=FA "10.66" > (rcd-vc-increase-decimal-revision-number "10.66") =A1=FA "10.67" > (rcd-vc-increase-decimal-revision-number "10.67") =A1=FA "10.68" > (rcd-vc-increase-decimal-revision-number "10.68") =A1=FA "10.69" > (rcd-vc-increase-decimal-revision-number "10.69") =A1=FA "10.70" > (rcd-vc-increase-decimal-revision-number "10.70") =A1=FA "10.71" > (rcd-vc-increase-decimal-revision-number "10.71") =A1=FA "10.72" > (rcd-vc-increase-decimal-revision-number "10.71") =A1=FA "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. Two different ways, each part on it's own, or as one macro. Much simpler than your decimal handling. I suggest to change your database scheme and store those as integers there too so you don't need to convert back and forth. Even better, skip the database and keep version number directly in your paper which you hopefully write in an org file ;-). (defun rcd-vc-increase-major-number (version) (aset version 0 (1+ (aref version 0)))) (defun rcd-vc-increase-minor-number (version) (aset version 1 (1+ (aref version 1)))) (defun rcd-vc-increase-revision-number (version) (aset version 2 (1+ (aref version 2)))) (defmacro incr-version (version-part version) `(cond ((equal ,version-part 'major) (aset ,version 0 (1+ (aref ,version 0)))) ((equal ,version-part 'minor) (aset ,version 1 (1+ (aref ,version 1)))) ((equal ,version-part 'revision) (aset ,version 2 (1+ (aref ,version 2)))))) (defun version-string (version) (format "%s.%s.%s" (aref version 0) (aref version 1) (aref version 2))) Eaxmple of usage: (defvar my-version [0 0 0]) (rcd-vc-increase-revision-number my-version) (version-string my-version) (incr-version 'major my-version) (incr-version 'minor my-version) (incr-version 'revision my-version) (version-string my-version)