2

How to use large decimal numbers with fixed precision, like money amount, in emacs lisp? For example, I'm writing a function that takes amount of money as a parameter. When I pass large float like 999999999999999.01 it looses precision and becomes 999999999999999.0. I didn't find fixed type in manual. My workarounds are:

  1. Pass two integers separately, integer part and fraction part - like dollars and cents
  2. Pass amount as string and parse it to two integers,

but both of this approaches will be less convenient for users.

Drew
  • 75,699
  • 9
  • 109
  • 225
  • 1
    You could use a single integer and then divide it by your fixed number whenever you need to display it. From what I recall, elisp lacks proper bit shifting, so "proper" fixed point numbers can only be approximated with multiplication and division. –  Nov 19 '18 at 19:22

1 Answers1

4

You could use the fractional representation of numbers from calc.

I am not sure why you think that passing the amount as string is inconvenient for the user.

I would pass that input to calc and adapt the precision to the length of the string.

Example:

(calc-frac-mode 1)
(setq str "999999999999999.01")
(setq var-x (calc-eval (list (format "pfrac(%s)" str) 'calc-internal-prec (length str)) 'raw))
(setq var-y (calc-eval "pfrac(1.01)" 'raw))
(setq var-z (math-add var-x var-y))
(calc-eval (list "pfloat($)" 'calc-internal-prec (calc-eval "floor(log10(abs($))+3)" 'raw var-z)) nil var-z)

The result of that elisp segment is 1000000000000000.02.

Tobias
  • 32,569
  • 1
  • 34
  • 75