unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* New library num-base-converters
@ 2017-08-14 17:26 Tino Calancha
  2017-08-14 17:48 ` Ted Zlatanov
  2017-08-15  7:55 ` Stefan Monnier
  0 siblings, 2 replies; 10+ messages in thread
From: Tino Calancha @ 2017-08-14 17:26 UTC (permalink / raw)
  To: Emacs developers; +Cc: Tino Calancha



Hi,

a simple library providing base converters for integers.

Convert integers between bases 2, 8, 10 and 16 is
a common task in the engineering and science applications.

I've being using for years several bash scripts calling `bc';
having a library written in elisp sounds like a better idea: it
will work regardless on the OS.

I think this library have its place in both, the core and ELPA.
What do you think?

;;; For Emacs master branch:
--8<-----------------------------cut here---------------start------------->8---
commit d00f1fc6a315e65d28f5212731f537ea9fb82050
Author: Tino Calancha <tino.calancha@gmail.com>
Date:   Tue Aug 15 02:09:38 2017 +0900

     New library 'num-base-converters'

     * lisp/num-base-converters.el: New file.
     * test/lisp/num-base-converters-tests.el: Add test suite.
     * etc/NEWS (New Modes and Packages in Emacs 26.1):
     Announce it.

diff --git a/etc/NEWS b/etc/NEWS
index 3f38153048..4ec6671f1f 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -1093,6 +1093,9 @@ processes on exit.

  * New Modes and Packages in Emacs 26.1

+** New library num-base-converters' to convert integers between
+different bases.
+
  ** New Elisp data-structure library 'radix-tree'.

  ** New library 'xdg' with utilities for some XDG standards and specs.
diff --git a/lisp/num-base-converters.el b/lisp/num-base-converters.el
new file mode 100644
index 0000000000..dd31d13d2b
--- /dev/null
+++ b/lisp/num-base-converters.el
@@ -0,0 +1,152 @@
+;;; num-base-converters.el --- Convert integers between different numeric bases  -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; Author: Tino Calancha <tino.calancha@gmail.com>
+;; Keywords: convenience, numbers, converters, tools
+;; Created: Tue Aug 15 02:04:55 JST 2017
+;; Version: 0.1
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software; you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Commentary:
+ 
+;; This library defines the command `nbc-number-base-converter' to
+;; convert a given integer in a numeric base to a different base.
+;;
+;; For instance, 10 in hexadecimal is 'A':
+;; (nbc-number-base-converter "10" 10 16)
+;; => "A"
+;;
+;; In addition, this file adds the following commands to convert
+;; between the most common bases (2, 8, 10, 16):
+;; `nbc-hex2dec', `nbc-hex2oct', `nbc-hex2bin'
+;; `nbc-dec2hex', `nbc-dec2oct', `nbc-dec2bin'
+;; `nbc-oct2hex', `nbc-oct2dec', `nbc-oct2bin'
+;; `nbc-bin2hex', `nbc-bin2dec', `nbc-bin2oct'.
+
+;;; Code:
+ 
+
+(require 'calc-bin)
+(eval-when-compile (require 'rx))
+
+(defgroup num-base-converters nil
+  "Convert integers between different numeric bases."
+  :group 'nbc)
+
+(defcustom nbc-define-aliases nil
+  "If non-nil, create aliases without prefix 'nbc' for the converters."
+  :type 'boolean
+  :group 'nbc)
+
+ 
+
+(defun nbc-number-base-converter (num base-in base-out)
+  "Translate NUM, a string representing an integer, to a different base.
+BASE-IN, an integer, is the basis of the input NUM.
+BASE-OUT, an integer, is the basis to display NUM."
+  (interactive
+   (let ((num (read-string "Number: "))
+         (base-in (read-number "Base input: "))
+         (base-out (read-number "Base output: ")))
+     (list num base-in base-out)))
+  (unless (stringp num)
+    (signal 'wrong-type-argument (list 'stringp num)))
+  (unless (and (>= base-in 2) (<= base-in 36) (>= base-out 2) (<= base-out 36))
+    (user-error "Base `b' must satisfy 2 <= b <= 36: base-in `%d' base-out `%d'"
+                base-in base-out))
+  (let* ((case-fold-search nil)
+         (input (progn
+                  (pcase num ; Drop base info from NUMB.
+                    ((rx (and string-start
+                              (let _u (or "b" "0x" "o")
+                                   (let v (one-or-more not-newline)) string-end)))
+                     (setq num v))
+                    ((rx (and string-start "#"
+                              (let _u (or "b" "x" "o" (and (one-or-more digit) "r")))
+                              (let v (one-or-more not-newline)) string-end))
+                     (setq num v)))
+                  (condition-case nil
+                      ;; Translate to canonical syntaxis: #(base)r(number).
+                      (read (format "#%dr%s" base-in num))
+	                (invalid-read-syntax
+                     (user-error "Wrong input: `%s' for base `%s'"
+                                 num base-in))))))
+    (condition-case nil
+        (let* ((calc-number-radix base-out)
+               (output (math-format-radix input)))
+          (pcase output
+            ((rx (and string-start
+                      (let _u (zero-or-one (and (zero-or-more digit) "#"))
+                           (let v (and (one-or-more not-newline) string-end)))))
+             (setq output v))) ; Drop base info from OUTPUT.
+          (message "%s base %s = %s base %s" num base-in output base-out)
+          output)
+      (wrong-type-argument
+       (user-error "Wrong input: `%s' for base `%s'" num base-in)))))
+
+ 
+;;; Add translatros for the most common basis: decimal, hexadecimal,
+;;  octal and binary.
+(eval-when-compile
+  (defmacro nbc--create-converters-1 ()
+    (let ((bases (list "hex" "dec" "oct" "bin"))
+          forms)
+      (dolist (base-out bases)
+        (dolist (base-in bases)
+          (if (equal base-out base-in)
+              nil
+            (push `(nbc--create-command ,base-in ,base-out) forms))))
+      `(progn ,@forms)))
+
+  (defmacro nbc--create-command (base-in base-out)
+    (let* ((input-fn
+            (lambda (x)
+              (pcase x
+                (`"hex" (cons "hexadecimal" 16))
+                (`"dec" (cons "decimal" 10))
+                (`"oct" (cons "octal" 8))
+                (`"bin" (cons "binary" 2)))))
+           (in-lst (funcall input-fn base-in))
+           (base-in-name (car in-lst))
+           (out-lst (funcall input-fn base-out))
+           (func-name (format "nbc-%s2%s" base-in
+                              (substring (car out-lst) 0 3)))
+           (prefix-len (length "nbc-"))
+           (docstring (format "Translate NUM, a string, from %s to %s."
+                              (car in-lst) (car out-lst)))
+           (ispec (format "sNumber in %s: " (car in-lst))))
+      `(progn
+         (when (bound-and-true-p nbc-define-aliases)
+           (defalias (intern ,(substring func-name prefix-len))
+             (intern ,func-name)))
+         (defun ,(intern func-name) ,(list 'num)
+           ,docstring (interactive ,ispec)
+           (let ((res (nbc-number-base-converter
+                       num ,(cdr in-lst) ,(cdr out-lst))))
+             (message "%s %s = %s %s"
+                      num ,base-in-name res ,(car out-lst))
+             res))))))
+
+(defun nbc--create-converters ()
+  "Create converters between the bases 2, 8, 10 and 16."
+  (nbc--create-converters-1))
+
+(nbc--create-converters)
+
+(provide 'num-base-converters)
+;;; num-base-converters.el ends here
diff --git a/test/lisp/num-base-converters-tests.el b/test/lisp/num-base-converters-tests.el
new file mode 100644
index 0000000000..c6ac2912b9
--- /dev/null
+++ b/test/lisp/num-base-converters-tests.el
@@ -0,0 +1,86 @@
+;;; num-base-converters-tests.el --- Test suite for num-base-converters. -*- lexical-binding: t -*-
+
+;; Copyright (C) 2017 Free Software Foundation, Inc.
+
+;; This file is part of GNU Emacs.
+
+;; GNU Emacs is free software: you can redistribute it and/or modify
+;; it under the terms of the GNU General Public License as published by
+;; the Free Software Foundation, either version 3 of the License, or
+;; (at your option) any later version.
+
+;; GNU Emacs is distributed in the hope that it will be useful,
+;; but WITHOUT ANY WARRANTY; without even the implied warranty of
+;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+;; GNU General Public License for more details.
+
+;; You should have received a copy of the GNU General Public License
+;; along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.
+
+;;; Code:
+(require 'ert)
+(require 'num-base-converters)
+
+
+(ert-deftest nbc-test-converters ()
+  ;; Input is case-insensitive.
+  (dolist (x (list "a" "A"))
+    (should (equal "10" (nbc-hex2dec x)))
+    (should (equal "12" (nbc-hex2oct x)))
+    (should (equal "1010" (nbc-hex2bin x))))
+  ;;
+  (should (equal "A" (nbc-dec2hex "10")))
+  (should (equal "12" (nbc-dec2oct "10")))
+  (should (equal "1010" (nbc-dec2bin "10")))
+  ;;
+  (should (equal "3F" (nbc-oct2hex "77")))
+  (should (equal "63" (nbc-oct2dec "77")))
+  (should (equal "111111" (nbc-oct2bin "77")))
+  ;;
+  (should (equal "A" (nbc-bin2hex "1010")))
+  (should (equal "10" (nbc-bin2dec "1010")))
+  (should (equal "12" (nbc-bin2oct "1010"))))
+
+(ert-deftest nbc-test-nbc-number-base-converter ()
+  ;; Bases `b' must be: 2 <= b <= 36:
+  (should-error (nbc-number-base-converter "10" 37 10))
+  (should-error (nbc-number-base-converter "10" 10 37))
+  (should-error (nbc-number-base-converter "10" 10 1))
+  (should-error (nbc-number-base-converter "10" 1 10))
+  ;; Invalid input:
+  (should-error (nbc-number-base-converter "1a" 8 10))
+  (should-error (nbc-number-base-converter "az" 16 10))
+  (should-error (nbc-number-base-converter "3" 2 10))
+  (should-error (nbc-number-base-converter "z" 10 8))
+  ;;
+  (should (equal "8" (nbc-number-base-converter "10" 8 16)))
+  (should (equal "10" (nbc-number-base-converter "8" 16 8)))
+  (should (equal "12" (nbc-number-base-converter "10" 10 8)))
+  (should (equal "10" (nbc-number-base-converter "12" 8 10)))
+  (should (equal "1000" (nbc-number-base-converter "10" 8 2)))
+  (should (equal "10" (nbc-number-base-converter "1000" 2 8)))
+  ;;
+  (should (equal "10" (nbc-number-base-converter "a" 16 10)))
+  (should (equal "10" (nbc-number-base-converter "A" 16 10)))
+  (should (equal "A" (nbc-number-base-converter "10" 10 16)))
+  (should (equal "1010" (nbc-number-base-converter "a" 16 2)))
+  (should (equal "1010" (nbc-number-base-converter "A" 16 2)))
+  (should (equal "A" (nbc-number-base-converter "1010" 2 16)))
+  ;;
+  (should (equal "1010" (nbc-number-base-converter "10" 10 2)))
+  (should (equal "10" (nbc-number-base-converter "1010" 2 10))))
+
+(ert-deftest nbc-test-nbc-number-base-converter ()
+  (let (nbc-define-aliases)
+    (nbc--create-converters)
+    (should (fboundp 'nbc-oct2dec))
+    (should-not (fboundp 'oct2dec))
+    (setq nbc-define-aliases t)
+    ;; It should create the aliases, i.e. `oct2dec' etc.
+    (nbc--create-converters)
+    (should (fboundp 'oct2dec))))
+
+
+(provide 'num-base-converters-tests)
+
+;; num-base-converters-tests.el ends here

--8<-----------------------------cut here---------------end--------------->8---
In GNU Emacs 26.0.50 (build 1, x86_64-pc-linux-gnu, GTK+ Version 3.22.11)
  of 2017-08-14
Repository revision: 5ba4c7d16b800864fa14b8a981e33f6aa6fa94d6


;;; For Elpa:
--8<-----------------------------cut here---------------start------------->8---
;;; num-base-converters.el --- Convert integers between different numeric bases  -*- lexical-binding: t -*-

;; Copyright (C) 2017 Free Software Foundation, Inc.

;; Author: Tino Calancha <tino.calancha@gmail.com>
;; Maintainer: Tino Calancha <tino.calancha@gmail.com>
;; Keywords: convenience, numbers, converters, tools

;; Created: Tue Aug 15 02:04:55 JST 2017
;; Package-Requires: ((emacs "24.4"))
;; Version: 0.1

;; GNU Emacs is free software; you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.


;; This file is part of GNU Emacs.

;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
;; GNU General Public License for more details.

;; You should have received a copy of the GNU General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.

;;; Commentary:

;; This library defines the command `nbc-number-base-converter' to
;; convert a given integer in a numeric base to a different base.
;;
;; For instance, 10 in hexadecimal is 'A':
;; (nbc-number-base-converter "10" 10 16)
;; => "A"
;;
;; In addition, this file adds the following commands to convert
;; between the most common bases (2, 8, 10, 16):
;; `nbc-hex2dec', `nbc-hex2oct', `nbc-hex2bin'
;; `nbc-dec2hex', `nbc-dec2oct', `nbc-dec2bin'
;; `nbc-oct2hex', `nbc-oct2dec', `nbc-oct2bin'
;; `nbc-bin2hex', `nbc-bin2dec', `nbc-bin2oct'.

;;; Code:


(require 'calc-bin)

(defgroup num-base-converters nil
   "Convert integers between different numeric bases."
   :group 'nbc)

(defcustom nbc-define-aliases nil
   "If non-nil, create aliases without prefix 'nbc' for the converters."
   :type 'boolean
   :group 'nbc)



(defun nbc-number-base-converter (num base-in base-out)
   "Translate NUM, a string representing an integer, to a different base.
BASE-IN, an integer, is the basis of the input NUM.
BASE-OUT, an integer, is the basis to display NUM."
   (interactive
    (let ((num (read-string "Number: "))
          (base-in (read-number "Base input: "))
          (base-out (read-number "Base output: ")))
      (list num base-in base-out)))
   (unless (stringp num)
     (signal 'wrong-type-argument (list 'stringp num)))
   (unless (and (>= base-in 2) (<= base-in 36) (>= base-out 2) (<= base-out 36))
     (error "Base `b' must satisfy 2 <= b <= 36: base-in `%d' base-out `%d'"
            base-in base-out))
   (let* ((case-fold-search nil)
          (input (progn
                   ;; Drop base info from NUMB.
                   (cond ((string-match "\\`\\(b\\|0x\\|o\\)\\(.+\\)\\'" num)
                          (setq num (match-string 2 num)))
                         ((string-match "\\`#\\(b\\|x\\|o\\|[0-9]+r\\)\\(.+\\)\\'" num)
                          (setq num (match-string 2 num))))
                   (condition-case nil
                       ;; Translate to canonical syntaxis: #(base)r(number).
                       (read (format "#%dr%s" base-in num))
                     (invalid-read-syntax
                      (error "Wrong input: `%s' for base `%s'" num base-in))))))
     (condition-case nil
         (let* ((regexp "\\`\\([0-9]*#\\)?\\(.+\\'\\)")
                (calc-number-radix base-out)
                (output (math-format-radix input)))
           (when (string-match regexp output) ; Drop base info from OUTPUT.
             (setq output (match-string-no-properties 2 output)))
           (message "%s base %s = %s base %s" num base-in output base-out)
           output)
       (wrong-type-argument
        (error "Wrong input: `%s' for base `%s'" num base-in)))))


;;; Add translatros for the most common basis: decimal, hexadecimal,
;;  octal and binary.
(eval-when-compile
   (defmacro nbc--create-converters-1 ()
     (let ((bases (list "hex" "dec" "oct" "bin"))
           forms)
       (dolist (base-out bases)
         (dolist (base-in bases)
           (if (equal base-out base-in)
               nil
             (push `(nbc--create-command ,base-in ,base-out) forms))))
       `(progn ,@forms)))

   (defmacro nbc--create-command (base-in base-out)
     (let* ((input-fn
             (lambda (x)
               (pcase x
                 (`"hex" (cons "hexadecimal" 16))
                 (`"dec" (cons "decimal" 10))
                 (`"oct" (cons "octal" 8))
                 (`"bin" (cons "binary" 2)))))
            (in-lst (funcall input-fn base-in))
            (base-in-name (car in-lst))
            (out-lst (funcall input-fn base-out))
            (func-name (format "nbc-%s2%s" base-in
                               (substring (car out-lst) 0 3)))
            (prefix-len (length "nbc-"))
            (docstring (format "Translate NUM, a string, from %s to %s."
                               (car in-lst) (car out-lst)))
            (ispec (format "sNumber in %s: " (car in-lst))))
       `(progn
          (when (bound-and-true-p nbc-define-aliases)
            (defalias (intern ,(substring func-name prefix-len))
              (intern ,func-name)))
          (defun ,(intern func-name) ,(list 'num)
            ,docstring (interactive ,ispec)
            (let ((res (nbc-number-base-converter
                        num ,(cdr in-lst) ,(cdr out-lst))))
              (message "%s %s = %s %s"
                       num ,base-in-name res ,(car out-lst))
              res))))))

(defun nbc--create-converters ()
   "Create converters between the bases 2, 8, 10 and 16."
   (nbc--create-converters-1))

(nbc--create-converters)

(provide 'num-base-converters)
;;; num-base-converters.el ends here

--8<-----------------------------cut here---------------end--------------->8---



^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-14 17:26 New library num-base-converters Tino Calancha
@ 2017-08-14 17:48 ` Ted Zlatanov
  2017-08-15  2:11   ` raman
  2017-08-15  7:55 ` Stefan Monnier
  1 sibling, 1 reply; 10+ messages in thread
From: Ted Zlatanov @ 2017-08-14 17:48 UTC (permalink / raw)
  To: emacs-devel

On Tue, 15 Aug 2017 02:26:18 +0900 (JST) Tino Calancha <tino.calancha@gmail.com> wrote: 

TC> a simple library providing base converters for integers.

TC> Convert integers between bases 2, 8, 10 and 16 is
TC> a common task in the engineering and science applications.
...
TC> I think this library have its place in both, the core and ELPA.
TC> What do you think?

I like it in the core. It was requested a few years ago:
https://lists.gnu.org/archive/html/help-gnu-emacs/2011-03/msg00535.html

Ted




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-14 17:48 ` Ted Zlatanov
@ 2017-08-15  2:11   ` raman
  2017-08-15  2:50     ` Tino Calancha
  0 siblings, 1 reply; 10+ messages in thread
From: raman @ 2017-08-15  2:11 UTC (permalink / raw)
  To: emacs-devel

Ted Zlatanov <tzz@lifelogs.com> writes:

this functionality is present in calculator.el --
I've never called it from lisp though. That module provides additional
conversions --- including radians->degrees etc.
> On Tue, 15 Aug 2017 02:26:18 +0900 (JST) Tino Calancha <tino.calancha@gmail.com> wrote: 
>
> TC> a simple library providing base converters for integers.
>
> TC> Convert integers between bases 2, 8, 10 and 16 is
> TC> a common task in the engineering and science applications.
> ...
> TC> I think this library have its place in both, the core and ELPA.
> TC> What do you think?
>
> I like it in the core. It was requested a few years ago:
> https://lists.gnu.org/archive/html/help-gnu-emacs/2011-03/msg00535.html
>
> Ted
>
>

-- 



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-15  2:11   ` raman
@ 2017-08-15  2:50     ` Tino Calancha
  2017-08-15  5:25       ` Drew Adams
  0 siblings, 1 reply; 10+ messages in thread
From: Tino Calancha @ 2017-08-15  2:50 UTC (permalink / raw)
  To: raman; +Cc: Tino Calancha, Emacs developers



On Mon, 14 Aug 2017, raman wrote:

> Ted Zlatanov <tzz@lifelogs.com> writes:
>
> this functionality is present in calculator.el --
> I've never called it from lisp though. That module provides additional
> conversions --- including radians->degrees etc.
Thanks.
Sure, you can get this functionality with calc.el as well:
indeed num-base-converters.el internally calls `calc-number-radix'.

One point of this library is the convenience of not having to
know anything about neither calculator.el nor calc.el to get
the answer with easy.

Every Emacs user will understand the following:
M-x nbc-hex2dec ff RET
"ff hexadecimal = 255 decimal"

M-: (nbc-oct2dec "644") RET
=> 420

;; Or just `hex2dec' and `oct2dec' if you customize
;; `nbc-define-aliases' to non-nil.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: New library num-base-converters
  2017-08-15  2:50     ` Tino Calancha
@ 2017-08-15  5:25       ` Drew Adams
  2017-08-15  6:35         ` Tino Calancha
  0 siblings, 1 reply; 10+ messages in thread
From: Drew Adams @ 2017-08-15  5:25 UTC (permalink / raw)
  To: Tino Calancha, raman; +Cc: Emacs developers

> > this functionality is present in calculator.el --

> Sure, you can get this functionality with calc.el as well:
> indeed num-base-converters.el internally calls `calc-number-radix'.
> 
> One point of this library is the convenience of not having to
> know anything about neither calculator.el nor calc.el to get
> the answer with easy.
> 
> Every Emacs user will understand the following:
> M-x nbc-hex2dec ff RET
> "ff hexadecimal = 255 decimal"
> 
> M-: (nbc-oct2dec "644") RET
> => 420
> 
> ;; Or just `hex2dec' and `oct2dec' if you customize
> ;; `nbc-define-aliases' to non-nil.

(format "%d" #xff)  ; hex to decimal
--> "255"

(format "%x" 255)   ; decimal to hex
--> "ff"

(format "%d" #o644) ; octal to decimal
--> "420"

(format "%o" 420)   ; decimal to octal
--> "644"

And didn't Pascal B. point this out in the thread previously cited?

    (format "#8r%o #10r%d #16r%x" 42 42 42)
    --> "#8r52 #10r42 #16r2a"

https://lists.gnu.org/archive/html/help-gnu-emacs/2011-03/msg00531.html



^ permalink raw reply	[flat|nested] 10+ messages in thread

* RE: New library num-base-converters
  2017-08-15  5:25       ` Drew Adams
@ 2017-08-15  6:35         ` Tino Calancha
  0 siblings, 0 replies; 10+ messages in thread
From: Tino Calancha @ 2017-08-15  6:35 UTC (permalink / raw)
  To: Drew Adams; +Cc: raman, Emacs developers, Tino Calancha

[-- Attachment #1: Type: text/plain, Size: 1500 bytes --]



On Mon, 14 Aug 2017, Drew Adams wrote:

>> One point of this library is the convenience of not having to
>> know anything about neither calculator.el nor calc.el to get
>> the answer with easy.
>>
>> Every Emacs user will understand the following:
>> M-x nbc-hex2dec ff RET
>> "ff hexadecimal = 255 decimal"
>>
>> M-: (nbc-oct2dec "644") RET
>> => 420
>>
>> ;; Or just `hex2dec' and `oct2dec' if you customize
>> ;; `nbc-define-aliases' to non-nil.
>
> (format "%d" #xff)  ; hex to decimal
> --> "255"
>
> (format "%x" 255)   ; decimal to hex
> --> "ff"
>
> (format "%d" #o644) ; octal to decimal
> --> "420"
>
> (format "%o" 420)   ; decimal to octal
> --> "644"
For an user familiar with the Emacs '#' read syntaxis might be OK.
But for the average user, it's better to accept more input formats:
(nbc-hex2dec "#xff")
"255"
(nbc-hex2dec "ff")
"255"
(nbc-hex2dec "0xff")
"255"



> And didn't Pascal B. point this out in the thread previously cited?
>
>    (format "#8r%o #10r%d #16r%x" 42 42 42)
>    --> "#8r52 #10r42 #16r2a"

*) cannot be called interactively.
*) This covers the base range 2 <= b <= 16.  Even worse, it silently
    returns a wrong result for b > 16:
(format "#16r%x" 42)
"#16r2a"
(format "#17r%x" 42)
"#17r2a"
(format "#37r%x" 42)
"#37r2a"

Compare with:

(nbc-number-base-converter "42" 10 16)
"2A"
(nbc-number-base-converter "42" 10 17)
"28"
(nbc-number-base-converter "42" 10 37)
;; Signal error: Base ‘b’ must satisfy 2 <= b <= 36: base-in ‘10’ base-out 
‘37’

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-14 17:26 New library num-base-converters Tino Calancha
  2017-08-14 17:48 ` Ted Zlatanov
@ 2017-08-15  7:55 ` Stefan Monnier
  2017-08-15  9:49   ` Tino Calancha
  2017-08-15 13:40   ` Ted Zlatanov
  1 sibling, 2 replies; 10+ messages in thread
From: Stefan Monnier @ 2017-08-15  7:55 UTC (permalink / raw)
  To: emacs-devel

> +(defun nbc-number-base-converter (num base-in base-out)
> +  "Translate NUM, a string representing an integer, to a different base.
> +BASE-IN, an integer, is the basis of the input NUM.
> +BASE-OUT, an integer, is the basis to display NUM."

Having a string as both input and output is a bad API, I think.
All one needs is basically to add a `base` arg to number-to-string
(there's already one for string-to-number).


        Stefan




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-15  7:55 ` Stefan Monnier
@ 2017-08-15  9:49   ` Tino Calancha
  2017-08-15 15:24     ` Stefan Monnier
  2017-08-15 13:40   ` Ted Zlatanov
  1 sibling, 1 reply; 10+ messages in thread
From: Tino Calancha @ 2017-08-15  9:49 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: Tino Calancha, Emacs developers



On Tue, 15 Aug 2017, Stefan Monnier wrote:

>> +(defun nbc-number-base-converter (num base-in base-out)
>> +  "Translate NUM, a string representing an integer, to a different base.
>> +BASE-IN, an integer, is the basis of the input NUM.
>> +BASE-OUT, an integer, is the basis to display NUM."
>
> Having a string as both input and output is a bad API, I think.
It's better API than not having API at all; it provides me the flexibility
to handle input as '0xff', '#xff' or 'ff'.  Not that bad.

> All one needs is basically to add a `base` arg to number-to-string
> (there's already one for string-to-number).
Then we are again limited to 2 < b < 16 bases.  In the old thread
the OP asking for this feature wanted to use base 36.
The presented lib can handle 2 <= b <= 36.



^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-15  7:55 ` Stefan Monnier
  2017-08-15  9:49   ` Tino Calancha
@ 2017-08-15 13:40   ` Ted Zlatanov
  1 sibling, 0 replies; 10+ messages in thread
From: Ted Zlatanov @ 2017-08-15 13:40 UTC (permalink / raw)
  To: emacs-devel

On Tue, 15 Aug 2017 03:55:19 -0400 Stefan Monnier <monnier@iro.umontreal.ca> wrote: 

>> +(defun nbc-number-base-converter (num base-in base-out)
>> +  "Translate NUM, a string representing an integer, to a different base.
>> +BASE-IN, an integer, is the basis of the input NUM.
>> +BASE-OUT, an integer, is the basis to display NUM."

SM> Having a string as both input and output is a bad API, I think.

It's OK for a parser :)

SM> All one needs is basically to add a `base` arg to number-to-string
SM> (there's already one for string-to-number).

I think that's a good improvement as well, especially if it works for
larger bases and errors out if the base is out of range.

On Tue, 15 Aug 2017 18:49:45 +0900 (JST) Tino Calancha <tino.calancha@gmail.com> wrote: 

TC> It's better API than not having API at all; it provides me the flexibility
TC> to handle input as '0xff', '#xff' or 'ff'.  Not that bad.

So one approach is to write your library so it parses and converts in
one shot, as it does today. This limits its utility and reusability.

The other approach is to follow Stefan's suggestion to improve
`number-to-string' and `string-to-number' in the core, and then to add
to your library a dedicated parser that can accept all the possible
inputs you want. So your library would be that parser plus glue to
`number-to-string' and `string-to-number'. Maybe also a fallback for
backwards compatibility if the core `number-to-string' and
`string-to-number' are less capable. I think that solution would benefit
Emacs developers and users the most, long-term.

Ted




^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: New library num-base-converters
  2017-08-15  9:49   ` Tino Calancha
@ 2017-08-15 15:24     ` Stefan Monnier
  0 siblings, 0 replies; 10+ messages in thread
From: Stefan Monnier @ 2017-08-15 15:24 UTC (permalink / raw)
  To: emacs-devel

>>> +(defun nbc-number-base-converter (num base-in base-out)
>>> +  "Translate NUM, a string representing an integer, to a different base.
>>> +BASE-IN, an integer, is the basis of the input NUM.
>>> +BASE-OUT, an integer, is the basis to display NUM."
>> Having a string as both input and output is a bad API, I think.
> It's better API than not having API at all; it provides me the flexibility
> to handle input as '0xff', '#xff' or 'ff'.  Not that bad.

What do you mean by "handle"?  It only lets you convert the string to
a string in a different base, which is rarely what you need.
Instead you will generally want to extract the number it represents,
then modify it a bit than turn it back into a string in a given base.

>> All one needs is basically to add a `base` arg to number-to-string
>> (there's already one for string-to-number).
> Then we are again limited to 2 < b < 16 bases.

No.  We can similarly extend string-to-number to accept bases > 16.

If you want to provide it without changing Emacs's core, you can make it
a package that exports <pkg>-string-to-number and
<pkg>-number-to-string, but the API should separate the conversion from
a string to a number and back, rather than force you to conversions
between strings, which force you to do things like "baseN-to-dec, then
string-to-number, do something, then number-to-string, then
dec-to-baseN", which is just silly (and inefficient to boot).


        Stefan




^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2017-08-15 15:24 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2017-08-14 17:26 New library num-base-converters Tino Calancha
2017-08-14 17:48 ` Ted Zlatanov
2017-08-15  2:11   ` raman
2017-08-15  2:50     ` Tino Calancha
2017-08-15  5:25       ` Drew Adams
2017-08-15  6:35         ` Tino Calancha
2017-08-15  7:55 ` Stefan Monnier
2017-08-15  9:49   ` Tino Calancha
2017-08-15 15:24     ` Stefan Monnier
2017-08-15 13:40   ` Ted Zlatanov

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

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).