1
/********************************************************************
2
* gnc-numeric.c -- an exact-number library for gnucash. *
3
* Copyright (C) 2000 Bill Gribble *
5
* This program is free software; you can redistribute it and/or *
6
* modify it under the terms of the GNU General Public License as *
7
* published by the Free Software Foundation; either version 2 of *
8
* the License, or (at your option) any later version. *
10
* This program is distributed in the hope that it will be useful, *
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
13
* GNU General Public License for more details. *
15
* You should have received a copy of the GNU General Public License*
16
* along with this program; if not, contact: *
18
* Free Software Foundation Voice: +1-617-542-5942 *
19
* 59 Temple Place - Suite 330 Fax: +1-617-542-2652 *
20
* Boston, MA 02111-1307, USA gnu@gnu.org *
22
*******************************************************************/
32
#include "gnc-engine-util.h"
33
#include "gnc-numeric.h"
36
* - use longer intermediate values to make operations
37
* 64-bit-overflow-proof
40
/* static short module = MOD_ENGINE; */
42
static const char * _numeric_error_strings[] =
45
"Argument is not a valid number",
46
"Intermediate result overflow",
47
"Argument denominators differ in GNC_DENOM_FIXED operation",
48
"Remainder part in GNC_RND_NEVER operation"
51
static gint64 gnc_numeric_lcd(gnc_numeric a, gnc_numeric b);
53
/********************************************************************
55
********************************************************************/
58
gnc_numeric_zero_p(gnc_numeric a) {
59
if(gnc_numeric_check(a)) {
63
if((a.num == 0) && (a.denom != 0)) {
72
/********************************************************************
73
* gnc_numeric_negative_p
74
********************************************************************/
77
gnc_numeric_negative_p(gnc_numeric a) {
78
if(gnc_numeric_check(a)) {
82
if((a.num < 0) && (a.denom != 0)) {
91
/********************************************************************
92
* gnc_numeric_positive_p
93
********************************************************************/
96
gnc_numeric_positive_p(gnc_numeric a) {
97
if(gnc_numeric_check(a)) {
101
if((a.num > 0) && (a.denom != 0)) {
111
/********************************************************************
112
* gnc_numeric_compare
113
* returns 1 if a>b, -1 if b>a, 0 if a == b
114
********************************************************************/
117
gnc_numeric_compare(gnc_numeric a, gnc_numeric b) {
120
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
123
ab = a.num * b.denom;
124
ba = b.num * a.denom;
138
/********************************************************************
140
********************************************************************/
143
gnc_numeric_eq(gnc_numeric a, gnc_numeric b) {
144
return ((a.num == b.num) && (a.denom == b.denom));
148
/********************************************************************
150
********************************************************************/
153
gnc_numeric_equal(gnc_numeric a, gnc_numeric b) {
154
if(((a.denom > 0) && (b.denom > 0)) ||
155
((a.denom < 0) && (b.denom < 0))) {
156
return ((a.num * b.denom) == (a.denom * b.num));
164
/********************************************************************
166
* would a and b be equal() if they were both converted to the same
168
********************************************************************/
171
gnc_numeric_same(gnc_numeric a, gnc_numeric b, gint64 denom,
173
gnc_numeric aconv, bconv;
175
aconv = gnc_numeric_convert(a, denom, how);
176
bconv = gnc_numeric_convert(b, denom, how);
178
return(gnc_numeric_equal(aconv, bconv));
183
/********************************************************************
185
********************************************************************/
188
gnc_numeric_add(gnc_numeric a, gnc_numeric b,
189
gint64 denom, gint how) {
192
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
193
return gnc_numeric_error(GNC_ERROR_ARG);
196
if((denom == GNC_DENOM_AUTO) &&
197
(how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_FIXED) {
198
if(a.denom == b.denom) {
201
else if(b.num == 0) {
204
else if(a.num == 0) {
208
return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
222
/* get an exact answer.. same denominator is the common case. */
223
if(a.denom == b.denom) {
224
sum.num = a.num + b.num;
228
sum.num = a.num*b.denom + b.num*a.denom;
229
sum.denom = a.denom*b.denom;
232
if((denom == GNC_DENOM_AUTO) &&
233
((how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_LCD)) {
234
denom = gnc_numeric_lcd(a, b);
235
how = how & GNC_NUMERIC_RND_MASK;
238
return gnc_numeric_convert(sum, denom, how);
242
/********************************************************************
243
* gnc_numeric_add_fixed
244
********************************************************************/
247
gnc_numeric_add_fixed(gnc_numeric a, gnc_numeric b) {
248
return gnc_numeric_add(a, b, GNC_DENOM_AUTO,
249
GNC_DENOM_FIXED | GNC_RND_NEVER);
253
/********************************************************************
255
********************************************************************/
258
gnc_numeric_sub(gnc_numeric a, gnc_numeric b,
259
gint64 denom, gint how) {
262
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
263
return gnc_numeric_error(GNC_ERROR_ARG);
266
if((denom == GNC_DENOM_AUTO) &&
267
(how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_FIXED) {
268
if(a.denom == b.denom) {
271
else if(b.num == 0) {
274
else if(a.num == 0) {
278
return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
292
/* get an exact answer.. same denominator is the common case. */
293
if(a.denom == b.denom) {
294
diff.num = a.num - b.num;
295
diff.denom = a.denom;
298
diff.num = a.num*b.denom - b.num*a.denom;
299
diff.denom = a.denom*b.denom;
302
if((denom == GNC_DENOM_AUTO) &&
303
((how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_LCD)) {
304
denom = gnc_numeric_lcd(a, b);
305
how = how & GNC_NUMERIC_RND_MASK;
307
return gnc_numeric_convert(diff, denom, how);
311
/********************************************************************
312
* gnc_numeric_sub_fixed
313
********************************************************************/
316
gnc_numeric_sub_fixed(gnc_numeric a, gnc_numeric b) {
317
return gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
318
GNC_DENOM_FIXED | GNC_RND_NEVER);
322
/********************************************************************
324
********************************************************************/
327
gnc_numeric_mul(gnc_numeric a, gnc_numeric b,
328
gint64 denom, gint how) {
331
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
332
return gnc_numeric_error(GNC_ERROR_ARG);
335
if((denom == GNC_DENOM_AUTO) &&
336
(how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_FIXED) {
337
if(a.denom == b.denom) {
340
else if(b.num == 0) {
343
else if(a.num == 0) {
347
return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
361
product.num = a.num*b.num;
362
product.denom = a.denom*b.denom;
364
if(product.denom < 0) {
365
product.num = -product.num;
366
product.denom = -product.denom;
369
if((denom == GNC_DENOM_AUTO) &&
370
((how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_LCD)) {
371
denom = gnc_numeric_lcd(a, b);
372
how = how & GNC_NUMERIC_RND_MASK;
375
return gnc_numeric_convert(product, denom, how);
379
/********************************************************************
381
********************************************************************/
384
gnc_numeric_div(gnc_numeric a, gnc_numeric b,
385
gint64 denom, gint how) {
386
gnc_numeric quotient;
388
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
389
return gnc_numeric_error(GNC_ERROR_ARG);
392
if((denom == GNC_DENOM_AUTO) &&
393
(how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_FIXED) {
394
if(a.denom == b.denom) {
397
else if(a.denom == 0) {
401
return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
416
if(a.denom == b.denom) {
417
quotient.num = a.num;
418
quotient.denom = b.num;
421
quotient.num = a.num*b.denom;
422
quotient.denom = a.denom*b.num;
425
if(quotient.denom < 0) {
426
quotient.num = -quotient.num;
427
quotient.denom = -quotient.denom;
430
if((denom == GNC_DENOM_AUTO) &&
431
((how & GNC_NUMERIC_DENOM_MASK) == GNC_DENOM_LCD)) {
432
denom = gnc_numeric_lcd(a, b);
433
how = how & GNC_NUMERIC_RND_MASK;
436
return gnc_numeric_convert(quotient, denom, how);
439
/********************************************************************
441
* negate the argument
442
********************************************************************/
445
gnc_numeric_neg(gnc_numeric a) {
446
if(gnc_numeric_check(a)) {
447
return gnc_numeric_error(GNC_ERROR_ARG);
449
return gnc_numeric_create(- a.num, a.denom);
452
/********************************************************************
454
* return the absolute value of the argument
455
********************************************************************/
458
gnc_numeric_abs(gnc_numeric a) {
459
if(gnc_numeric_check(a)) {
460
return gnc_numeric_error(GNC_ERROR_ARG);
462
return gnc_numeric_create(ABS(a.num), a.denom);
465
/********************************************************************
466
* gnc_numeric_convert
467
********************************************************************/
470
gnc_numeric_convert(gnc_numeric in, gint64 denom, gint how) {
478
double ratio, logratio;
481
if(gnc_numeric_check(in)) {
482
return gnc_numeric_error(GNC_ERROR_ARG);
485
if(denom == GNC_DENOM_AUTO) {
486
switch(how & GNC_NUMERIC_DENOM_MASK) {
487
case GNC_DENOM_EXACT:
491
case GNC_DENOM_REDUCE:
492
/* reduce the input to a relatively-prime fraction */
493
return gnc_numeric_reduce(in);
496
case GNC_DENOM_FIXED:
497
if(in.denom != denom) {
498
return gnc_numeric_error(GNC_ERROR_DENOM_DIFF);
505
case GNC_DENOM_SIGFIG:
506
ratio = fabs(gnc_numeric_to_double(in));
511
logratio = log10(ratio);
512
logratio = ((logratio > 0.0) ?
513
(floor(logratio)+1.0) : (ceil(logratio)));
515
sigfigs = GNC_NUMERIC_GET_SIGFIGS(how);
517
if(sigfigs-logratio >= 0) {
518
denom = (gint64)(pow(10, sigfigs-logratio));
521
denom = -((gint64)(pow(10, logratio-sigfigs)));
524
how = how & ~GNC_DENOM_SIGFIG & ~GNC_NUMERIC_SIGFIGS_MASK;
528
/* this is a no-op. */
534
/* make sure we need to do the work */
535
if(in.denom == denom) {
539
/* if the denominator of the input value is negative, get rid of that. */
541
in.num = in.num * (- in.denom);
545
sign = (in.num < 0) ? -1 : 1;
547
/* if the denominator is less than zero, we are to interpret it as
548
* the reciprocal of its magnitude. */
552
temp_a = (in.num < 0) ? -in.num : in.num;
553
temp_bc = in.denom * denom;
554
remainder = in.num % temp_bc;
555
out.num = in.num / temp_bc;
559
/* do all the modulo and int division on positive values to make
560
* things a little clearer. Reduce the fraction denom/in.denom to
561
* help with range errors (FIXME : need bigger intermediate rep) */
563
temp.denom = in.denom;
564
temp = gnc_numeric_reduce(temp);
566
out.num = in.num * temp.num;
567
out.num = (out.num < 0) ? -out.num : out.num;
568
remainder = out.num % temp.denom;
569
out.num = out.num / temp.denom;
577
out.num = out.num + 1;
583
out.num = out.num + 1;
590
case GNC_RND_PROMOTE:
591
out.num = out.num + 1;
594
case GNC_RND_ROUND_HALF_DOWN:
596
if((2 * remainder) > in.denom*denom) {
597
out.num = out.num + 1;
600
else if((2 * remainder) > temp.denom) {
601
out.num = out.num + 1;
605
case GNC_RND_ROUND_HALF_UP:
607
if((2 * remainder) >= in.denom*denom) {
608
out.num = out.num + 1;
611
else if((2 * remainder ) >= temp.denom) {
612
out.num = out.num + 1;
618
if((2 * remainder) > in.denom*denom) {
619
out.num = out.num + 1;
621
else if((2 * remainder) == in.denom*denom) {
623
out.num = out.num + 1;
628
if((2 * remainder ) > temp.denom) {
629
out.num = out.num + 1;
631
else if((2 * remainder) == temp.denom) {
633
out.num = out.num + 1;
640
return gnc_numeric_error(GNC_ERROR_REMAINDER);
645
out.num = (sign > 0) ? out.num : (-out.num);
651
/********************************************************************
653
* Find the least common multiple of the denominators of
655
********************************************************************/
658
gnc_numeric_lcd(gnc_numeric a, gnc_numeric b) {
659
gint64 current_divisor = 2;
661
gint64 three_count = 0;
665
if(gnc_numeric_check(a) || gnc_numeric_check(b)) {
666
return GNC_ERROR_ARG;
669
if(b.denom < a.denom) {
670
small_denom = b.denom;
674
small_denom = a.denom;
678
/* special case: smaller divides smoothly into larger */
679
if((big_denom % small_denom) == 0) {
683
max_square = small_denom;
685
/* the LCM algorithm : take the union of the prime factors of the
686
* two args and multiply them together. To do this, we find the
687
* successive prime factors of the smaller denominator and eliminate
688
* them from the larger denominator, then multiply the smaller by
689
* the remains of the larger. */
690
while(current_divisor * current_divisor <= max_square) {
691
if(((small_denom % current_divisor) == 0) &&
692
((big_denom % current_divisor) == 0)) {
693
big_denom = big_denom / current_divisor;
696
if(current_divisor == 2) {
699
else if(three_count == 3) {
700
current_divisor += 4;
704
current_divisor += 2;
709
if((current_divisor > small_denom) ||
710
(current_divisor > big_denom)) {
715
return small_denom * big_denom;
720
/********************************************************************
722
* reduce a fraction by GCF elimination. This is NOT done as a
723
* part of the arithmetic API unless GNC_DENOM_REDUCE is specified
724
* as the output denominator.
725
********************************************************************/
728
gnc_numeric_reduce(gnc_numeric in) {
730
gint64 current_divisor = 2;
732
gint64 num = (in.num < 0) ? (- in.num) : in.num ;
733
gint64 denom = in.denom;
737
if(gnc_numeric_check(in)) {
738
return gnc_numeric_error(GNC_ERROR_ARG);
741
/* the strategy is to eliminate common factors from
742
* 2 up to 'max', where max is the smaller of the smaller
743
* part of the fraction and the sqrt of the larger part of
744
* the fraction. There's also the special case of the
745
* smaller of fraction parts being a common factor.
747
* we test for 2 and 3 first, and thereafter skip all even numbers
748
* and all odd multiples of 3 (that's every third odd number,
749
* i.e. 9, 15, 21), thus the three_count stuff. */
751
/* special case: one side divides evenly by the other */
755
else if((num > denom) && (num % denom == 0)) {
759
else if ((num <= denom) && (denom % num == 0)) {
764
max_square = (num > denom) ? denom : num;
766
/* normal case: test 2, then 3, 5, 7, 11, etc.
767
* (skip multiples of 2 and 3) */
768
while(current_divisor * current_divisor <= max_square) {
769
if((num % current_divisor == 0) &&
770
(denom % current_divisor == 0)) {
771
num = num / current_divisor;
772
denom = denom / current_divisor;
775
if(current_divisor == 2) {
778
else if(three_count == 3) {
779
current_divisor += 4;
783
current_divisor += 2;
788
if((current_divisor > num) ||
789
(current_divisor > denom)) {
794
/* all calculations are done on positive num, since it's not
795
* well defined what % does for negative values */
796
out.num = (in.num < 0) ? (- num) : num;
801
/********************************************************************
802
* double_to_gnc_numeric
803
********************************************************************/
806
double_to_gnc_numeric(double in, gint64 denom, gint how) {
814
if((denom == GNC_DENOM_AUTO) && (how & GNC_DENOM_SIGFIG)) {
815
if(fabs(in) < 10e-20) {
819
logval = log10(fabs(in));
820
logval = ((logval > 0.0) ?
821
(floor(logval)+1.0) : (ceil(logval)));
823
sigfigs = GNC_NUMERIC_GET_SIGFIGS(how);
824
if(sigfigs-logval >= 0) {
825
denom = (gint64)(pow(10, sigfigs-logval));
828
denom = -((gint64)(pow(10, logval-sigfigs)));
831
how = how & ~GNC_DENOM_SIGFIG & ~GNC_NUMERIC_SIGFIGS_MASK;
834
int_part = (gint64)(floor(fabs(in)));
835
frac_part = in - (double)int_part;
837
int_part = int_part * denom;
838
frac_part = frac_part * (double)denom;
840
switch(how & GNC_NUMERIC_RND_MASK) {
842
frac_int = (gint64)floor(frac_part);
846
frac_int = (gint64)ceil(frac_part);
850
frac_int = (gint64)frac_part;
854
case GNC_RND_ROUND_HALF_UP:
855
frac_int = (gint64)rint(frac_part);
859
frac_int = (gint64)floor(frac_part);
860
if(frac_part != (double) frac_int) {
861
/* signal an error */
866
out.num = int_part + frac_int;
871
/********************************************************************
872
* gnc_numeric_to_double
873
********************************************************************/
876
gnc_numeric_to_double(gnc_numeric in) {
878
return (double)in.num/(double)in.denom;
881
return (double)(in.num * in.denom);
886
/********************************************************************
888
********************************************************************/
891
gnc_numeric_create(gint64 num, gint64 denom) {
899
/********************************************************************
901
********************************************************************/
904
gnc_numeric_error(int error_code) {
905
if(abs(error_code) < 5) {
906
// PERR("%s", _numeric_error_strings[ - error_code]);
908
return gnc_numeric_create(error_code, 0LL);
912
/********************************************************************
914
********************************************************************/
917
gnc_numeric_zero(void) {
918
return gnc_numeric_create(0LL, 1LL);
922
/********************************************************************
924
********************************************************************/
927
gnc_numeric_num(gnc_numeric a) {
932
/********************************************************************
934
********************************************************************/
937
gnc_numeric_denom(gnc_numeric a) {
942
/********************************************************************
943
* gnc_numeric_add_with_error
944
********************************************************************/
947
gnc_numeric_add_with_error(gnc_numeric a, gnc_numeric b,
948
gint64 denom, gint how,
949
gnc_numeric * error) {
951
gnc_numeric sum = gnc_numeric_add(a, b, denom, how);
952
gnc_numeric exact = gnc_numeric_add(a, b, GNC_DENOM_AUTO,
954
gnc_numeric err = gnc_numeric_sub(sum, exact, GNC_DENOM_AUTO,
963
/********************************************************************
964
* gnc_numeric_sub_with_error
965
********************************************************************/
968
gnc_numeric_sub_with_error(gnc_numeric a, gnc_numeric b,
969
gint64 denom, gint how,
970
gnc_numeric * error) {
972
gnc_numeric diff = gnc_numeric_sub(a, b, denom, how);
973
gnc_numeric exact = gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
975
gnc_numeric err = gnc_numeric_sub(diff, exact, GNC_DENOM_AUTO,
984
/********************************************************************
985
* gnc_numeric_mul_with_error
986
********************************************************************/
989
gnc_numeric_mul_with_error(gnc_numeric a, gnc_numeric b,
990
gint64 denom, gint how,
991
gnc_numeric * error) {
993
gnc_numeric prod = gnc_numeric_mul(a, b, denom, how);
994
gnc_numeric exact = gnc_numeric_mul(a, b, GNC_DENOM_AUTO,
996
gnc_numeric err = gnc_numeric_sub(prod, exact, GNC_DENOM_AUTO,
1005
/********************************************************************
1006
* gnc_numeric_div_with_error
1007
********************************************************************/
1010
gnc_numeric_div_with_error(gnc_numeric a, gnc_numeric b,
1011
gint64 denom, gint how,
1012
gnc_numeric * error) {
1014
gnc_numeric quot = gnc_numeric_div(a, b, denom, how);
1015
gnc_numeric exact = gnc_numeric_div(a, b, GNC_DENOM_AUTO,
1017
gnc_numeric err = gnc_numeric_sub(quot, exact,
1018
GNC_DENOM_AUTO, GNC_DENOM_REDUCE);
1026
gnc_numeric_check(gnc_numeric in) {
1028
return GNC_ERROR_OK;
1034
return GNC_ERROR_ARG;
1038
/********************************************************************
1039
* gnc_numeric text IO
1040
********************************************************************/
1043
gnc_numeric_to_string(gnc_numeric n) {
1045
long long int tmpnum = n.num;
1046
long long int tmpdenom = n.denom;
1048
result = g_strdup_printf("%lld/%lld", tmpnum, tmpdenom);
1054
string_to_gnc_numeric(const gchar* str, gnc_numeric *n) {
1055
/* Read a gnc_numeric from str, skipping any leading whitespace, and
1056
returning a pointer to just past the last byte read. Return NULL
1059
long long int tmpnum;
1060
long long int tmpdenom;
1062
if(!str) return NULL;
1064
/* must use "<" here because %n's effects aren't well defined */
1065
if(sscanf(str, " " GNC_SCANF_LLD "/" GNC_SCANF_LLD "%n",
1066
&tmpnum, &tmpdenom, &num_read) < 2) {
1070
n->denom = tmpdenom;
1071
return(str + num_read);
1074
#ifdef _GNC_NUMERIC_TEST
1077
gnc_numeric_print(gnc_numeric in) {
1079
if(gnc_numeric_check(in)) {
1080
retval = g_strdup_printf("<ERROR> [%lld / %lld]",
1081
(long long int) in.num,
1082
(long long int) in.denom);
1085
retval = g_strdup_printf("[%lld / %lld]",
1086
(long long int) in.num,
1087
(long long int) in.denom);
1093
main(int argc, char ** argv) {
1094
gnc_numeric a = gnc_numeric_create(1, 3);
1095
gnc_numeric b = gnc_numeric_create(1, 4);
1097
gnc_numeric d = gnc_numeric_create(1, 2);
1102
printf("add exact : %s + %s = %s\n",
1103
gnc_numeric_print(a), gnc_numeric_print(b),
1104
gnc_numeric_print(gnc_numeric_add(a, b,
1109
printf("add least : %s + %s = %s\n",
1110
gnc_numeric_print(a), gnc_numeric_print(b),
1111
gnc_numeric_print(gnc_numeric_add(a, b,
1113
GNC_DENOM_REDUCE)));
1115
printf("add 100ths (banker's): %s + %s = %s\n",
1116
gnc_numeric_print(a), gnc_numeric_print(b),
1117
gnc_numeric_print(gnc_numeric_add(a, b, 100,
1120
c = gnc_numeric_add_with_error(a, b, 100, GNC_RND_ROUND, &err);
1121
printf("add 100ths/error : %s + %s = %s + (error) %s\n\n",
1122
gnc_numeric_print(a), gnc_numeric_print(b),
1123
gnc_numeric_print(c),
1124
gnc_numeric_print(err));
1126
printf("sub exact : %s - %s = %s\n",
1127
gnc_numeric_print(a), gnc_numeric_print(b),
1128
gnc_numeric_print(gnc_numeric_sub(a, b, GNC_DENOM_AUTO,
1131
printf("sub least : %s - %s = %s\n",
1132
gnc_numeric_print(a), gnc_numeric_print(b),
1133
gnc_numeric_print(gnc_numeric_sub(a, b,
1135
GNC_DENOM_REDUCE)));
1137
printf("sub 100ths : %s - %s = %s\n",
1138
gnc_numeric_print(a), gnc_numeric_print(b),
1139
gnc_numeric_print(gnc_numeric_sub(a, b, 100,
1142
c = gnc_numeric_sub_with_error(a, b, 100, GNC_RND_FLOOR, &err);
1143
printf("sub 100ths/error : %s - %s = %s + (error) %s\n\n",
1144
gnc_numeric_print(a), gnc_numeric_print(b),
1145
gnc_numeric_print(c),
1146
gnc_numeric_print(err));
1148
printf("mul exact : %s * %s = %s\n",
1149
gnc_numeric_print(a), gnc_numeric_print(b),
1150
gnc_numeric_print(gnc_numeric_mul(a, b, GNC_DENOM_AUTO,
1153
printf("mul least : %s * %s = %s\n",
1154
gnc_numeric_print(a), gnc_numeric_print(b),
1155
gnc_numeric_print(gnc_numeric_mul(a, b, GNC_DENOM_AUTO,
1156
GNC_DENOM_REDUCE)));
1158
printf("mul 100ths : %s * %s = %s\n",
1159
gnc_numeric_print(a), gnc_numeric_print(b),
1160
gnc_numeric_print(gnc_numeric_mul(a, b, 100,
1163
c = gnc_numeric_mul_with_error(a, b, 100, GNC_RND_ROUND, &err);
1164
printf("mul 100ths/error : %s * %s = %s + (error) %s\n\n",
1165
gnc_numeric_print(a), gnc_numeric_print(b),
1166
gnc_numeric_print(c),
1167
gnc_numeric_print(err));
1169
printf("div exact : %s / %s = %s\n",
1170
gnc_numeric_print(a), gnc_numeric_print(b),
1171
gnc_numeric_print(gnc_numeric_div(a, b, GNC_DENOM_AUTO,
1174
printf("div least : %s / %s = %s\n",
1175
gnc_numeric_print(a), gnc_numeric_print(b),
1176
gnc_numeric_print(gnc_numeric_div(a, b, GNC_DENOM_AUTO,
1177
GNC_DENOM_REDUCE)));
1179
printf("div 100ths : %s / %s = %s\n",
1180
gnc_numeric_print(a), gnc_numeric_print(b),
1181
gnc_numeric_print(gnc_numeric_div(a, b, 100,
1184
c = gnc_numeric_div_with_error(a, b, 100, GNC_RND_ROUND, &err);
1185
printf("div 100ths/error : %s / %s = %s + (error) %s\n\n",
1186
gnc_numeric_print(a), gnc_numeric_print(b),
1187
gnc_numeric_print(c),
1188
gnc_numeric_print(err));
1190
printf("7/16 as float: %e\n",
1191
gnc_numeric_to_double(gnc_numeric_create(7, 16)));
1193
printf("7/16 as 100ths (floor): %s\n",
1194
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
1195
100, GNC_RND_FLOOR)));
1196
printf("7/16 as 100ths (ceil): %s\n",
1197
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
1198
100, GNC_RND_CEIL)));
1199
printf("7/16 as 100ths (trunc): %s\n",
1200
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
1201
100, GNC_RND_TRUNC)));
1202
printf("7/16 as 100ths (round): %s\n",
1203
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(7, 16),
1204
100, GNC_RND_ROUND)));
1206
printf("1511/1000 as 1/100 (round): %s\n",
1207
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1511, 1000),
1208
100, GNC_RND_ROUND)));
1209
printf("1516/1000 as 1/100 (round): %s\n",
1210
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1516, 1000),
1211
100, GNC_RND_ROUND)));
1212
printf("1515/1000 as 1/100 (round): %s\n",
1213
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1515, 1000),
1214
100, GNC_RND_ROUND)));
1215
printf("1525/1000 as 1/100 (round): %s\n",
1216
gnc_numeric_print(gnc_numeric_convert(gnc_numeric_create(1525, 1000),
1217
100, GNC_RND_ROUND)));
1219
printf("100023234 / 334216654 reduced: %s\n",
1220
gnc_numeric_print(gnc_numeric_reduce(gnc_numeric_create(10023234LL,
1222
printf("2^10*3^10*17^2 / 2^8*3^12 reduced: %s\n",
1224
(gnc_numeric_reduce(gnc_numeric_create(17474724864LL,
1226
printf("1024 / 1024^4 reduced: %s\n",
1228
(gnc_numeric_reduce(gnc_numeric_create(1024LL,
1229
1099511627776LL))));
1230
printf("reducing 100,000 times:\n\n");
1231
for(i = 0; i < 100000; i++) {
1232
gnc_numeric_reduce(gnc_numeric_create(17474724864LL,
1236
printf("add LCM: %s + %s = %s\n",
1237
gnc_numeric_print(b), gnc_numeric_print(d),
1238
gnc_numeric_print(gnc_numeric_add(b, d, GNC_DENOM_AUTO,
1241
printf("float to 6 sigfigs: %s\n",
1242
gnc_numeric_print(double_to_gnc_numeric(1.1234567890123,
1244
GNC_DENOM_SIGFIGS(6) |
1246
printf("float to 6 sigfigs: %s\n",
1247
gnc_numeric_print(double_to_gnc_numeric(.011234567890123,
1249
GNC_DENOM_SIGFIGS(6) |
1251
printf("float to 6 sigfigs: %s\n",
1252
gnc_numeric_print(double_to_gnc_numeric(1123.4567890123,
1254
GNC_DENOM_SIGFIGS(6) |
1256
printf("float to 6 sigfigs: %s\n",
1257
gnc_numeric_print(double_to_gnc_numeric(1.1234567890123e-5,
1259
GNC_DENOM_SIGFIGS(6) |
1261
printf("add to 4 sigfigs: %s + %s = %s\n",
1262
gnc_numeric_print(a), gnc_numeric_print(b),
1263
gnc_numeric_print(gnc_numeric_add(a, b,
1265
GNC_DENOM_SIGFIGS(4) |