architectural issue with gnc-numeric
Derek Atkins
warlord@MIT.EDU
Fri Jan 17 19:40:53 CST 2003
I've found an interesting architectural issue with the
gnc-numeric implementation. In particular, if you are
operating on two numbers of very high (but DIFFFERENT)
precision, you can cause the code to roll-over beyond the
size of the core data types.
As an example, let's say you want to represent some number, like
193.123456789 as 193123456789/1000000000 and want to add
5/10000000000 in order to "round" the number (see gnc-ui-util.c
PrintAmountInternal for an example). The gnc-numeric code notices
that the denom's are different so it tries to cross-multiply,
computing a new gnc-numeric as a.num*b.denom + b.num*a.denom over
a.denom*b.denom, and then reduces the result.
While that works right on paper, it unfortunately causes a wraparound
in the numerator because we've now tried to create a number greater
than 2^63-1 (MAX_LONGLONG). In particular, the largest numerator we
can hold is 9223372036854775807, but we're trying to compute
1931234567895000000000, which is obviously greater! The result is a
"broken" number. You can see this by changing "print_info.round" to
'1' in app-utils/test/test-print-parse-amount.c and watching it fail.
The obvious fix is to compute the least common multiple of the two
denominators, convert a and b up to the LCM, perform the addition (or
other operation), and then reduce. If I have time I'll try to make
this change.
However, I'm wondering (for historical reasons) why we chose to
represent numbers as fractions rather than, say, a fixed-point
notation? In understand the rounding issues with floating point, but
seriously, how often do we really need to represent rational but
"non-repeating decimal" numbers in GnuCash? I've certainly never been
given 1/3 of a dollar, or 1/3 of a share of stock. ;)
-derek
--
Derek Atkins, SB '93 MIT EE, SM '95 MIT Media Laboratory
Member, MIT Student Information Processing Board (SIPB)
URL: http://web.mit.edu/warlord/ PP-ASEL-IA N1NWH
warlord@MIT.EDU PGP key available
More information about the gnucash-devel
mailing list