From 1e8397b1940e1e6cd3eb1290113cc5aabbf4373c Mon Sep 17 00:00:00 2001 From: Derek Atkins Date: Sun, 19 Jan 2003 19:38:14 +0000 Subject: [PATCH] * src/engine/gnc-numeric.c -- be more intelligent when operating on numbers of different denominators. In particular, convert both numbers to the lcd and then operate on them, instead of assuming that a "cross-multiply" is safe. * src/app-utils/test/test-print-parse-amount.c -- add more tests for PrintAmountInternal by checking force_fit and round. Excercises a bug (fixed in this patch) where cross-multiplies were NOT safe. git-svn-id: svn+ssh://svn.gnucash.org/repo/gnucash/trunk@7848 57a11ea4-9604-0410-9ed3-97b8803252fd --- ChangeLog | 10 ++++++++ src/app-utils/test/test-print-parse-amount.c | 16 +++++++++--- src/engine/gnc-numeric.c | 27 +++++++++++++++----- 3 files changed, 44 insertions(+), 9 deletions(-) diff --git a/ChangeLog b/ChangeLog index ed25ca1cda..32105d16f3 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,13 @@ +2003-01-19 Derek Atkins + + * src/engine/gnc-numeric.c -- be more intelligent when operating + on numbers of different denominators. In particular, convert + both numbers to the lcd and then operate on them, instead of + assuming that a "cross-multiply" is safe. + * src/app-utils/test/test-print-parse-amount.c -- add more tests for + PrintAmountInternal by checking force_fit and round. Excercises + a bug (fixed in this patch) where cross-multiplies were NOT safe. + 2003-01-18 Derek Atkins * src/business/business-core/gncTaxTable.[ch]: add functions to diff --git a/src/app-utils/test/test-print-parse-amount.c b/src/app-utils/test/test-print-parse-amount.c index 86633b2678..6fe680fe4d 100644 --- a/src/app-utils/test/test-print-parse-amount.c +++ b/src/app-utils/test/test-print-parse-amount.c @@ -40,8 +40,6 @@ test_num (gnc_numeric n) print_info.min_decimal_places = 0; print_info.use_locale = 1; print_info.use_symbol = 0; - print_info.force_fit = 0; - print_info.round = 0; for (i = 1, fraction = 10; i < 9; i++, fraction *= 10) { @@ -50,16 +48,28 @@ test_num (gnc_numeric n) print_info.use_separators = 1; print_info.monetary = 1; print_info.max_decimal_places = i; + print_info.force_fit = 0; + print_info.round = 0; n1 = gnc_numeric_convert (n, fraction, GNC_RND_ROUND); test_num_print_info (n1, print_info); - + print_info.monetary = 0; test_num_print_info (n1, print_info); print_info.use_separators = 0; test_num_print_info (n1, print_info); + + print_info.round = 1; + test_num_print_info (n1, print_info); + + print_info.round = 0; + print_info.force_fit = 1; + test_num_print_info (n1, print_info); + + print_info.round = 1; + test_num_print_info (n1, print_info); } } diff --git a/src/engine/gnc-numeric.c b/src/engine/gnc-numeric.c index d79bea6468..1333fcd6bd 100644 --- a/src/engine/gnc-numeric.c +++ b/src/engine/gnc-numeric.c @@ -191,6 +191,7 @@ gnc_numeric gnc_numeric_add(gnc_numeric a, gnc_numeric b, gint64 denom, gint how) { gnc_numeric sum; + gint64 lcd; if(gnc_numeric_check(a) || gnc_numeric_check(b)) { return gnc_numeric_error(GNC_ERROR_ARG); @@ -228,8 +229,12 @@ gnc_numeric_add(gnc_numeric a, gnc_numeric b, sum.denom = a.denom; } else { - sum.num = a.num*b.denom + b.num*a.denom; - sum.denom = a.denom*b.denom; + /* ok, convert to the lcd and compute from there... */ + lcd = gnc_numeric_lcd(a,b); + sum.num = a.num*(lcd/a.denom) + b.num*(lcd/b.denom); + sum.denom = lcd; + // sum.num = a.num*b.denom + b.num*a.denom; + // sum.denom = a.denom*b.denom; } if((denom == GNC_DENOM_AUTO) && @@ -261,6 +266,7 @@ gnc_numeric gnc_numeric_sub(gnc_numeric a, gnc_numeric b, gint64 denom, gint how) { gnc_numeric diff; + gint64 lcd; if(gnc_numeric_check(a) || gnc_numeric_check(b)) { return gnc_numeric_error(GNC_ERROR_ARG); @@ -298,8 +304,12 @@ gnc_numeric_sub(gnc_numeric a, gnc_numeric b, diff.denom = a.denom; } else { - diff.num = a.num*b.denom - b.num*a.denom; - diff.denom = a.denom*b.denom; + /* ok, convert to the lcd and compute from there... */ + lcd = gnc_numeric_lcd(a,b); + diff.num = a.num*(lcd/a.denom) - b.num*(lcd/b.denom); + diff.denom = lcd; + // diff.num = a.num*b.denom - b.num*a.denom; + // diff.denom = a.denom*b.denom; } if((denom == GNC_DENOM_AUTO) && @@ -387,6 +397,7 @@ gnc_numeric gnc_numeric_div(gnc_numeric a, gnc_numeric b, gint64 denom, gint how) { gnc_numeric quotient; + gint64 lcd; if(gnc_numeric_check(a) || gnc_numeric_check(b)) { return gnc_numeric_error(GNC_ERROR_ARG); @@ -421,8 +432,12 @@ gnc_numeric_div(gnc_numeric a, gnc_numeric b, quotient.denom = b.num; } else { - quotient.num = a.num*b.denom; - quotient.denom = a.denom*b.num; + /* ok, convert to the lcd and compute from there... */ + lcd = gnc_numeric_lcd(a,b); + quotient.num = a.num*(lcd/a.denom); + quotient.denom = b.num*(lcd/b.denom); + // quotient.num = a.num*b.denom; + // quotient.denom = a.denom*b.num; } if(quotient.denom < 0) {