Emacs 单行计算器 ( M-x calculator
) 是否有内置方法将结果转换为金钱 - 例如转换3335856.7
为3,335,856.70
?
在使用以下线程中的代码编写我自己的修改之前,我想检查一下是否有人知道可以执行相同操作的内置设置:
答案1
编辑(2014 年 2 月 10 日):添加了一个新函数(即lawlist-calculator-update-display
),该函数修改了函数calculator-update-display
。每次在一系列计算期间更新显示时(例如,在达到总数之前的每个小计),显示现在都会反映最终总数 - 即使用逗号分隔符,删除不需要的额外零,并四舍五入到小数点后第四位。将(message "Copied
%s添加to the kill-ring." s)
到lawlist-calculator-copy
。
以下修改后的代码最初在屏幕上四舍五入到小数点右边 4 位数字;小数点左边每 3 位数字用逗号分隔符分隔;并且删除小数点右边任何不需要的多余零。
使用该函数lawlist-calculator-copy
将会把结果复制到 kill-ring 中 - 四舍五入到小数点右边 2 位数字,并且在小数点左边每 3 位数字包含一个逗号分隔符。
以下是有关四舍五入的文章链接: http://www.mathsisfun.com/rounding-numbers.html
number-conversion
我喜欢的数字转换四舍五入为 5——例如,1.555 将四舍五入为 1.56——@abo-abo编写的函数实现了这一目标。而(format "%0.2f" 1.555)
会向下舍入为 1.55,在美国处理货币时可能不应该使用(在我看来)。
(require 'calculator)
(setq calculator-prompt "Calculator: %s")
(setq calculator-number-digits 4)
(defalias 'calculator-get-prompt 'lawlist-calculator-get-prompt)
(defun lawlist-calculator-get-prompt ()
"Return a string to display.
The string is set not to exceed the screen width."
(let* ((calculator-prompt
(format calculator-prompt
(cond
((or calculator-output-radix calculator-input-radix)
(if (eq calculator-output-radix
calculator-input-radix)
(concat
(char-to-string
(car (rassq calculator-output-radix
calculator-char-radix)))
"=")
(concat
(if calculator-input-radix
(char-to-string
(car (rassq calculator-input-radix
calculator-char-radix)))
"=")
(char-to-string
(car (rassq calculator-output-radix
calculator-char-radix))))))
(calculator-deg "D=")
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; REMOVE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (t "=="))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; REPLACE WITH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(t ""))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(prompt
(concat calculator-prompt
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; REMOVE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; (cdr calculator-stack-display)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; REPLACE WITH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(if (floatp (car calculator-stack))
(group-number
(calculator-remove-zeros
;; round to 4 decimal points
;; The function number conversion will be used when copying.
(format "%.4f" (car calculator-stack))))
(cdr calculator-stack-display))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(cond (calculator-curnum
;; number being typed
(concat calculator-curnum "_"))
((and (= 1 (length calculator-stack))
calculator-display-fragile)
;; only the result is shown, next number will
;; restart
nil)
(t
;; waiting for a number or an operator
"?"))))
(trim (- (length prompt) (1- (window-width)))))
(if (<= trim 0)
prompt
(concat calculator-prompt
(substring prompt (+ trim (length calculator-prompt)))))))
(defalias 'calculator-update-display 'lawlist-calculator-update-display)
(defun lawlist-calculator-update-display (&optional force)
"Update the display.
If optional argument FORCE is non-nil, don't use the cached string."
(set-buffer calculator-buffer)
;; update calculator-stack-display
(if (or force
(not (eq (car calculator-stack-display) calculator-stack)))
(setq calculator-stack-display
(cons calculator-stack
(if calculator-stack
(concat
(let ((calculator-displayer
(if (and calculator-displayers
(= 1 (length calculator-stack)))
;; customizable display for a single value
(caar calculator-displayers)
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; REMOVE ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;; calculator-displayer
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; REPLACE WITH ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(calculator-remove-zeros
(group-number
(format "%.4f"
(string-to-number
(calculator-number-to-string calculator-stack)))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
)))
(mapconcat 'calculator-number-to-string
(reverse calculator-stack)
" " ))
" "
(and calculator-display-fragile
calculator-saved-list
(= (car calculator-stack)
(nth calculator-saved-ptr
calculator-saved-list))
(if (= 0 calculator-saved-ptr)
(format "[%s]" (length calculator-saved-list))
(format "[%s/%s]"
(- (length calculator-saved-list)
calculator-saved-ptr)
(length calculator-saved-list)))))
""))))
(let ((inhibit-read-only t))
(erase-buffer)
(insert (calculator-get-prompt)))
(set-buffer-modified-p nil)
(if calculator-display-fragile
(goto-char (1+ (length calculator-prompt)))
(goto-char (1- (point)))))
(defun lawlist-calculator-copy ()
"Copy current number to the `kill-ring'."
(interactive)
(let ((calculator-displayer
(or calculator-copy-displayer calculator-displayer))
(calculator-displayers
(if calculator-copy-displayer nil calculator-displayers)))
(calculator-enter)
;; remove trailing spaces and an index
(let (
(s
(if (floatp (car calculator-stack))
(group-number
(number-conversion
(format "%s" (car calculator-stack))))
(cdr calculator-stack-display))) )
(and s
(if (string-match "^\\([^ ]+\\) *\\(\\[[0-9/]+\\]\\)? *$" s)
(setq s (match-string 1 s)))
(kill-new s)
(message "Copied `%s` to the kill-ring." s)))))
;; http://stackoverflow.com/a/20101269/2112489
;; @abo-abo
(defun number-conversion (str)
(let ((x (read str)))
(format "%0.2f" (* 0.01 (round (* 100 x)))) ))
;; http://www.emacswiki.org/emacs/ElispCookbook#toc23
(defun group-number (num &optional size char)
"Format NUM as string grouped to SIZE with CHAR."
;; Based on code for `math-group-float' in calc-ext.el
(let* ((size (or size 3))
(char (or char ","))
(str (if (stringp num)
num
(number-to-string num)))
(pt (or (string-match "[^0-9a-zA-Z]" str) (length str))))
(while (> pt size)
(setq str (concat (substring str 0 (- pt size))
char
(substring str (- pt size)))
pt (- pt size)))
str))