GNU bug report logs -
#74760
29.4; Calc : calcFunc-rate does not produce negative results
Previous Next
To reply to this bug, email your comments to 74760 AT debbugs.gnu.org.
Toggle the display of automated, internal messages from the tracker.
Report forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 05:11:02 GMT)
Full text and
rfc822 format available.
Acknowledgement sent
to
Ting Boon Ghee <tingbg <at> gmail.com>
:
New bug report received and forwarded. Copy sent to
bug-gnu-emacs <at> gnu.org
.
(Tue, 10 Dec 2024 05:11:02 GMT)
Full text and
rfc822 format available.
Message #5 received at submit <at> debbugs.gnu.org (full text, mbox):
In GNU Emacs 29.4 (build 2, x86_64-pc-linux-gnu, GTK+ Version 3.24.42,
cairo version 1.18.0) of 2024-06-30, modified by Debian built on
sbuild
System Description: Debian GNU/Linux trixie/sid
Configured using:
'configure --build x86_64-linux-gnu --prefix=/usr
--sharedstatedir=/var/lib --libexecdir=/usr/libexec
--localstatedir=/var/lib --infodir=/usr/share/info
--mandir=/usr/share/man --with-libsystemd --with-pop=yes
--enable-locallisppath=/etc/emacs:/usr/local/share/emacs/29.4/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/29.4/site-lisp:/usr/share/emacs/site-lisp
--with-sound=alsa --without-gconf --with-mailutils
--with-native-compilation --build x86_64-linux-gnu --prefix=/usr
--sharedstatedir=/var/lib --libexecdir=/usr/libexec
--localstatedir=/var/lib --infodir=/usr/share/info
--mandir=/usr/share/man --with-libsystemd --with-pop=yes
--enable-locallisppath=/etc/emacs:/usr/local/share/emacs/29.4/site-lisp:/usr/local/share/emacs/site-lisp:/usr/share/emacs/29.4/site-lisp:/usr/share/emacs/site-lisp
--with-sound=alsa --without-gconf --with-mailutils
--with-native-compilation --with-pgtk 'CFLAGS=-g -O2
-Werror=implicit-function-declaration
-ffile-prefix-map=/build/reproducible-path/emacs-29.4+1=. -fstack-protector-strong
-fstack-clash-protection -Wformat -Werror=format-security
-fcf-protection -Wall' 'CPPFLAGS=-Wdate-time -D_FORTIFY_SOURCE=2'
LDFLAGS=-Wl,-z,relro'
Configured features:
ACL CAIRO DBUS FREETYPE GIF GLIB GMP GNUTLS GPM GSETTINGS HARFBUZZ
JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 MODULES
NATIVE_COMP NOTIFY INOTIFY PDUMPER PGTK PNG RSVG SECCOMP SOUND SQLITE3
THREADS TIFF TOOLKIT_SCROLL_BARS TREE_SITTER WEBP XIM GTK3 ZLIB
Important settings:
value of $LANG: en_SG.UTF-8
locale-coding-system: utf-8-unix
Major mode: Messages
Minor modes in effect:
global-git-commit-mode: t
magit-auto-revert-mode: t
denote-menu-bar-mode: t
server-mode: t
pdf-occur-global-minor-mode: t
windmove-mode: t
shell-dirtrack-mode: t
hyperbole-mode: t
override-global-mode: t
vertico-reverse-mode: t
vertico-multiform-mode: t
vertico-mode: t
minibuffer-electric-default-mode: t
minibuffer-depth-indicate-mode: t
global-corfu-mode: t
corfu-mode: t
auto-image-file-mode: t
global-eldoc-mode: t
show-paren-mode: t
electric-indent-mode: t
tab-bar-mode: t
file-name-shadow-mode: t
global-font-lock-mode: t
font-lock-mode: t
blink-cursor-mode: t
buffer-read-only: t
column-number-mode: t
line-number-mode: t
indent-tabs-mode: t
transient-mark-mode: t
auto-composition-mode: t
auto-encryption-mode: t
auto-compression-mode: t
Load-path shadows:
/home/boonghee/.emacs.d/elpa/transient-20241208.2227/transient hides /usr/share/emacs/29.4/lisp/transient
Features:
(macros hywconfig shadow filecache emacsbug cl-print calc-prog
calc-store repeat calc-trail calc-yank calc-stuff calc-math calcalg2
calcalg3 calc-fin 2048-game mc-edit-lines mc-hide-unmatched-lines-mode
mc-mark-more sgml-mode mc-cycle-cursors multiple-cursors-core
webdriver eieio-base ediff ediff-merg ediff-mult ediff-wind ediff-diff
ediff-help ediff-init ediff-util magit-bookmark magit-submodule
magit-blame magit-stash magit-reflog magit-bisect magit-push
magit-pull magit-fetch magit-clone magit-remote magit-commit
magit-sequence magit-notes magit-worktree magit-tag magit-merge
magit-branch magit-reset magit-files magit-refs magit-status magit
magit-repos magit-apply magit-wip magit-log magit-diff smerge-mode
diff git-commit magit-core magit-autorevert autorevert magit-margin
magit-transient magit-process with-editor log-edit pcvs-util add-log
magit-mode transient benchmark magit-git magit-base which-func
magit-section cursor-sensor dash vertico-flat loaddefs-gen lisp-mnt
tar-mode arc-mode archive-mode display-line-numbers shortdoc help-fns
radix-tree dabbrev pcmpl-unix calc-alg calc-mode calc-misc calc-forms
org-clock org-colview char-fold misearch multi-isearch cal-move
mm-archive mule-util notmuch notmuch-tree notmuch-jump notmuch-hello
notmuch-show notmuch-print notmuch-crypto notmuch-mua notmuch-message
notmuch-draft notmuch-maildir-fcc notmuch-address notmuch-company
notmuch-parser notmuch-wash coolj goto-addr icalendar notmuch-tag crm
notmuch-lib notmuch-compat sh-script smie executable calc-arith tabify
elfeed-link denote org-capture timezone hi-lock shr-color textsec
uni-scripts idna-mapping ucs-normalize uni-confusable textsec-check
calc-map calc-stat calc-vec calccomp calc-ext calc-menu calc-aent calc
calc-loaddefs rect calc-macs pdf-sync pdf-annot facemenu pdf-outline
pdf-links pdf-history network-stream url-http url-gw nsm url-cache
url-auth dired-aux bs elfeed-show elfeed-search elfeed-csv elfeed
elfeed-curl elfeed-log elfeed-db elfeed-lib xml-query orderless
hl-line diary-lib diary-loaddefs cal-iso face-remap org-agenda comp
comp-cstr warnings server cus-start vc-git diff-mode vc-dispatcher
org-indent oc-basic ol-eww ol-rmail ol-mhe ol-irc ol-info ol-gnus
nnselect ol-docview doc-view filenotify ol-bibtex bibtex ol-bbdb
ol-w3m ol-doi org-link-doi pdf-occur ibuf-ext ibuffer ibuffer-loaddefs
tablist tablist-filter semantic/wisent/comp semantic/wisent
semantic/wisent/wisent semantic/util-modes semantic/util semantic
semantic/tag semantic/lex semantic/fw mode-local cedet pdf-isearch
let-alist pdf-misc pdf-tools pdf-view jka-compr pdf-cache pdf-info tq
pdf-util pdf-macs image-mode exif dired-filetype-face advice
gnus-dired avy cus-edit hyperbole hinit hui hui-mouse hmouse-key imenu
hsys-flymake hui-menu hyrolo-menu hui-jmenu hibtypes hib-doc-id hyrolo
sort reveal klink hmouse-tag hsys-xref hib-kbd hui-mini hib-debbugs
hsys-www eww url-queue mm-url hib-social hypb-ert ert ewoc debug
backtrace hynote hywiki hasht thingatpt hactypes hsys-org org-element
org-persist xdg org-id org-refile avl-tree hsys-consult hsys-org-roam
hargs etags fileloop generator xref hpath tramp tramp-loaddefs
trampver tramp-integration files-x tramp-compat bookmark pp hmouse-sh
hsettings hproperty hbut hmouse-drv hui-window pulse color hycontrol
windmove view hui-select hbdata hgnus gnus-msg gnus-art mm-uu mml2015
mm-view mml-smime smime gnutls dig gnus-sum shr pixel-fill kinsoku
url-file svg dom gnus-group gnus-undo gnus-start gnus-dbus dbus xml
gnus-cloud nnimap nnmail mail-source utf7 nnoo parse-time iso8601
gnus-spec gnus-int gnus-range gnus-win gnus nnheader range wid-edit
hsmail message sendmail yank-media puny rfc822 mml mml-sec epa derived
epg rfc6068 epg-config gnus-util mm-decode mm-bodies mm-encode
mail-parse rfc2231 rfc2047 rfc2045 mm-util ietf-drums mail-prsvr
mailabbrev mail-utils gmm-utils mailheader hmail htz cal-julian hbmap
hmoccur hvar hypb org org-macro org-pcomplete org-list org-footnote
org-faces org-entities time-date noutline outline ob-emacs-lisp
ob-shell shell pcomplete ob-python python project treesit ob ob-tangle
org-src ob-ref ob-lob ob-table ob-exp ob-comint ob-core ob-eval
org-cycle org-table ol rx org-fold org-fold-core org-keys oc
org-loaddefs find-func cal-menu calendar cal-loaddefs org-version
org-compat org-macs format-spec locate dired dired-loaddefs compile
text-property-search comint ansi-osc ansi-color ring hversion
hload-path edmacro kmacro use-package-bind-key bind-key easy-mmode
use-package-core cl-extra help-mode icons vertico-reverse
vertico-multiform vertico avoid minibuf-eldef mb-depth marginalia
t-mouse corfu compat compat-30 image-file image-converter cus-load
finder-inf 2048-game-autoloads avy-autoloads bbdb-autoloads
consult-autoloads corfu-autoloads denote-autoloads
dired-filetype-face-autoloads eat-autoloads elfeed-autoloads
empv-autoloads golden-ratio-autoloads hyperbole-autoloads
kotl-autoloads hact set hhist magit-autoloads pcase
magit-section-autoloads dash-autoloads marginalia-autoloads
multiple-cursors-autoloads notmuch-autoloads orderless-autoloads
org-vcard-autoloads pdf-tools-autoloads pyim-basedict-autoloads
pyim-autoloads async-autoloads s-autoloads sketch-mode-autoloads
sudo-edit-autoloads tablist-autoloads transient-autoloads
vertico-autoloads webdriver-autoloads with-editor-autoloads info
compat-autoloads xr-autoloads package browse-url url url-proxy
url-privacy url-expand url-methods url-history url-cookie
generate-lisp-file url-domsuf url-util mailcap url-handlers url-parse
auth-source cl-seq eieio eieio-core cl-macs password-cache json subr-x
map byte-opt gv bytecomp byte-compile url-vars cl-loaddefs cl-lib rmc
iso-transl tooltip cconv eldoc paren electric uniquify ediff-hook
vc-hooks lisp-float-type elisp-mode mwheel term/pgtk-win pgtk-win
term/common-win pgtk-dnd tool-bar dnd fontset image regexp-opt fringe
tabulated-list replace newcomment text-mode lisp-mode prog-mode
register page tab-bar menu-bar rfn-eshadow isearch easymenu timer
select scroll-bar mouse jit-lock font-lock syntax font-core
term/tty-colors frame minibuffer nadvice seq simple cl-generic
indonesian philippine cham georgian utf-8-lang misc-lang vietnamese
tibetan thai tai-viet lao korean japanese eucjp-ms cp51932 hebrew
greek romanian slovak czech european ethiopic indian cyrillic chinese
composite emoji-zwj charscript charprop case-table epa-hook
jka-cmpr-hook help abbrev obarray oclosure cl-preloaded button
loaddefs theme-loaddefs faces cus-face macroexp files window
text-properties overlay sha1 md5 base64 format env code-pages mule
custom widget keymap hashtable-print-readable backquote threads
dbusbind inotify dynamic-setting system-font-setting
font-render-setting cairo gtk pgtk lcms2 multi-tty
make-network-process native-compile emacs)
Memory information:
((conses 16 5237599 667173)
(symbols 48 71711 58)
(strings 32 1424037 55655)
(string-bytes 1 170514731)
(vectors 16 413925)
(vector-slots 8 5868547 880391)
(floats 8 102807 2906)
(intervals 56 394849 46383)
(buffers 984 92))
Using Calc to compute the rate of return on an investment, negative returns will result in error.
;; Extract from manual on the description of this function
8.6.4 Related Financial Functions
---------------------------------
The ‘b T’ (‘calc-fin-rate’) [‘rate’] command computes the rate of return on an investment. This is also an inverse of ‘pv’: ‘rate(N, PAYMENT, AMOUNT)’ computes the value of RATE such that ‘pv(RATE, N, PAYMENT) = AMOUNT’. The result is expressed as a formula like ‘6.3%’.
;; Example of positive return working correctly
;; Calculations for N=1, Payment=110 Amount=100
;; Answer is 10% as expected
;; Using the calculator
M-x calc <RET> 1 <RET> 110 <RET> 100 <RET> b T
Answer is 10%
;; Evaluating the original function from calc-fin.el
(calcFunc-rate 1 110 100)
Answer : (float 1 -1)
;; Negative returns result in error
;; Calculations for N=1, Payment=90 Amount=100
;; Answer should be -10%
;; Using the calculator
M-x calc <RET> 1 <RET> 90 <RET> 100 <RET> b T
Result : rate(1, 90, 100)
Pressing '=' in the calculator subsequently gives the following message
Working... widen = (-1.59974 .. 199261559.20347)
Unable to bracket root: (-1.599740 .. 199261559.203470)
;; Evaluating the original function from calc-fin.el
(calcFunc-rate 1 90 100)
Evaluating the function produces this Backtrace message
Debugger entered--Lisp error: (wrong-type-argument "*Unable to bracket root" (intv 0 (float -159974 -5) (float 19926155920347 -5)))
math-reject-arg((intv 0 (float -159974 -5) (float 19926155920347 -5)) "*Unable to bracket root")
math-search-root((- (calcFunc-pv (var DUMMY var-DUMMY) 1 90 0) 100) (+ (/ 90 (* (var DUMMY var-DUMMY) (^ (+ (var DUMMY var-DUMMY) 1) 2))) (/ (- (/ 90 (+ (var DUMMY var-DUMMY) 1)) 90) (^ (var DUMMY var-DUMMY) 2))) (float 1 -4) (float -1000899910009 -11) (float 1 0) (float -55 0))
math-newton-search-root((- (calcFunc-pv (var DUMMY var-DUMMY) 1 90 0) 100) (+ (/ 90 (* (var DUMMY var-DUMMY) (^ (+ (var DUMMY var-DUMMY) 1) 2))) (/ (- (/ 90 (+ (var DUMMY var-DUMMY) 1)) 90) (^ (var DUMMY var-DUMMY) 2))) nil nil nil nil (float 1 -4) (float -1000899910009 -11) (float 1 0) (float -55 0))
math-find-root((calcFunc-eq (calcFunc-pv (var DUMMY var-DUMMY) 1 90 0) 100) (var DUMMY var-DUMMY) (intv 3 (float 1 -4) 1) t)
math-compute-rate(1 90 100 nil calcFunc-pv)
calcFunc-rate(1 90 100)
elisp--eval-last-sexp(nil)
eval-last-sexp(nil)
funcall-interactively(eval-last-sexp nil)
command-execute(eval-last-sexp)
;; Original definition of calcFunc-rate and math-compute-rate copied from calc-fin.el as follows
(defun calcFunc-rate (num pmt amount &optional lump)
(math-compute-rate num pmt amount lump 'calcFunc-pv))
(defun math-compute-rate (num pmt amount lump func)
(or (math-objectp num)
(math-reject-arg num 'numberp))
(or (math-objectp pmt)
(math-reject-arg pmt 'numberp))
(or (math-objectp amount)
(math-reject-arg amount 'numberp))
(or (null lump)
(math-objectp lump)
(math-reject-arg lump 'numberp))
(let ((root (math-find-root (list 'calcFunc-eq
(list func
'(var DUMMY var-DUMMY)
num
pmt
(or lump 0))
amount)
'(var DUMMY var-DUMMY)
'(intv 3 (float 1 -4) 1)
t)))
(if (math-vectorp root)
(nth 1 root)
root)))
;; My modified function definitions
(defmath my/rate (num pmt amount &optional lump)
(my/compute-rate num pmt amount lump 'calcFunc-pv))
(defmath my/compute-rate (num pmt amount lump func)
(or (math-objectp num)
(math-reject-arg num 'numberp))
(or (math-objectp pmt)
(math-reject-arg pmt 'numberp))
(or (math-objectp amount)
(math-reject-arg amount 'numberp))
(or (null lump)
(math-objectp lump)
(math-reject-arg lump 'numberp))
(let ((root (math-find-root (list 'calcFunc-eq
(list func
'(var DUMMY var-DUMMY)
num
pmt
(or lump 0))
amount)
'(var DUMMY var-DUMMY)
'(intv 3 -1 1)
t)))
(if (math-vectorp root)
(nth 1 root)
root)))
By changing the interval from '(intv 3 (float 1 -4) 1) to '(intv 3 -1 1), the correct answer of -10% for above example can be computed.
;; Evaluating my modified function
(calcFunc-my/rate 1 90 100)
Answer : (float -1 -1)
That is -10% as expected.
I am not sure if this is a bug or due to some restrictions or constrains elsewhere that the interval cannot be negative in the original function definition of math-compute-rate. Other than Rate, IRR function is also facing the same issue as the interval for math-compute-irr is also set as '(intv 3 (float 1 -4) 1).
Calculations can also be crosschecked with spreadsheets. Results should be same.
--
Best regards,
Boon Ghee
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 13:23:01 GMT)
Full text and
rfc822 format available.
Message #8 received at 74760 <at> debbugs.gnu.org (full text, mbox):
> Date: Tue, 10 Dec 2024 00:44:04 +0800
> From: Ting Boon Ghee <tingbg <at> gmail.com>
>
> Using Calc to compute the rate of return on an investment, negative returns will result in error.
Isn't it true that in the financial world there are no negative rates,
only positive rates written in red color? Maybe this explains what
you see?
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 13:46:02 GMT)
Full text and
rfc822 format available.
Message #11 received at 74760 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Negative rates do indeed exist in the real world. Central banks, for
example, have set their very short-term rates negative to deter savings
(depositor pays bank to save rather than the bank paying the depositor) and
encourage credit growth and reduce longer-term rates (lending or investing
in longer-term instruments). Of course, you won't get a negative-rate
mortgage, this scheme is focused on money-center banks, not retail
consumers. In other places like the commodity markets, you can also see
negatives for things you might not expect. Oil prices were driven negative
for a short time when there was no excess shipping capacity and the cost of
shipping hyperinflated.
On Tue, Dec 10, 2024 at 8:23 AM Eli Zaretskii <eliz <at> gnu.org> wrote:
> > Date: Tue, 10 Dec 2024 00:44:04 +0800
> > From: Ting Boon Ghee <tingbg <at> gmail.com>
> >
> > Using Calc to compute the rate of return on an investment, negative
> returns will result in error.
>
> Isn't it true that in the financial world there are no negative rates,
> only positive rates written in red color? Maybe this explains what
> you see?
>
>
>
>
[Message part 2 (text/html, inline)]
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 15:52:02 GMT)
Full text and
rfc822 format available.
Message #14 received at 74760 <at> debbugs.gnu.org (full text, mbox):
Hello,
could you please post a recipe?
TIA,
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 16:00:02 GMT)
Full text and
rfc822 format available.
Message #17 received at 74760 <at> debbugs.gnu.org (full text, mbox):
Eli Zaretskii <eliz <at> gnu.org> writes:
> Isn't it true that in the financial world there are no negative rates,
> only positive rates written in red color? Maybe this explains what
> you see?
It's probably not related but: this part of `calc-fin-rate' is clearly
suspicious:
(calc-to-percentage
(calc-normalize
(cons (if (calc-is-hyperbolic) 'calcFunc-ratel
(if (calc-is-hyperbolic) 'calcFunc-rateb ;; !@?!
'calcFunc-rate))
(calc-top-list-n n))))
Looks like one of those two identical `calc-is-hyperbolic' tests
must be replaced with `calc-is-inverse' (the second one?).
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 16:15:01 GMT)
Full text and
rfc822 format available.
Message #20 received at submit <at> debbugs.gnu.org (full text, mbox):
Michael Heerdegen via "Bug reports for GNU Emacs, the Swiss army knife
of text editors" <bug-gnu-emacs <at> gnu.org> writes:
> Hello,
>
> could you please post a recipe?
Hi,
The recipe is at the end of the mail.
--
Manuel Giraud
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 16:15:02 GMT)
Full text and
rfc822 format available.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 17:25:02 GMT)
Full text and
rfc822 format available.
Message #26 received at 74760 <at> debbugs.gnu.org (full text, mbox):
Ting Boon Ghee <tingbg <at> gmail.com> writes:
> I am not sure if this is a bug or due to some restrictions or
> constrains elsewhere that the interval cannot be negative in the
> original function definition of math-compute-rate.
It could be that the original authors just did not have this special
case in mind when writing the code, and there is no such reason.
Michael.
Information forwarded
to
bug-gnu-emacs <at> gnu.org
:
bug#74760
; Package
emacs
.
(Tue, 10 Dec 2024 18:43:02 GMT)
Full text and
rfc822 format available.
Message #29 received at 74760 <at> debbugs.gnu.org (full text, mbox):
[Message part 1 (text/plain, inline)]
Thanks everyone for response.
These financial functions (and more) are available in spreadsheets such as
Libreoffice Calc. There is no restriction for Rate to be negative in
Libreoffice Calc. One way to look at this is, from investment perspective,
it just means the series of payments is less than the initial outlay,
resulting in negative return.
The Info manual describes the Rate function as an inverse of ‘pv’:
‘rate(N, PAYMENT, AMOUNT)’ computes the value of RATE such that ‘pv(RATE,
N, PAYMENT) = AMOUNT’. So let's try PV.
If Rate = -0.1, N = 1, PAYMENT = 90, calculate PV. Thus,
M-x calc <RET> _0.1 <RET> 1 <RET> 90 <RET> b P
Answer : 100
This means PV function can accept Rate as a negative number.
I stumbled upon this issue because I was trying to recreate a table that I
had done previously in Libreoffice Calc into an Org Table. The table uses
Rate function to calculate a series of returns with a range of negative to
positive returns. The negative returns generated errors in the table fields.
I suppose Emacs Calc was developed long ago to mimic handheld calculators.
I'd wonder whether anyone is still using it as a "handheld" financial
calculator. Such functions are most useful in spreadsheets. Emacs now has
an implementation of a spreadsheet in the form of Org Table that uses Emacs
Calc. This does mean that it is restricted to what Emacs Calc can provide.
A missing function that I wish for is the XIRR function available in other
spreadsheet softwares.
--
Best regards,
Boon Ghee
[Message part 2 (text/html, inline)]
This bug report was last modified 189 days ago.
Previous Next
GNU bug tracking system
Copyright (C) 1999 Darren O. Benham,
1997,2003 nCipher Corporation Ltd,
1994-97 Ian Jackson.