architectural issue with gnc-numeric
Derek Atkins
warlord@MIT.EDU
Sun Jan 19 19:39:46 CST 2003
Hearing no objections I committed a change that implements this. I
ran the tests to make sure it still works, and added more tests to
PrintAmount to show the exercise of this bug. If you want to
reproduce the actual bug, keep the changes I just committed to
src/app-utils/test/test-print-parse-amount.c, but back out the changes
to src/engine/gnc-numeric.c and watch is blow up. :)
Enjoy!
-derek
Derek Atkins <warlord@MIT.EDU> writes:
> 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
> _______________________________________________
> gnucash-devel mailing list
> gnucash-devel@lists.gnucash.org
> https://lists.gnucash.org/mailman/listinfo/gnucash-devel
--
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