GnuCash c935c2f+
Loading...
Searching...
No Matches
Files | Data Structures | Enumerator | Variables
Numeric: Rational Number Handling w/ Rounding Error Control

The 'Numeric' functions provide a way of working with rational numbers while maintaining strict control over rounding errors when adding rationals with different denominators. More...

Files

file  gnc-numeric.h
 An exact-rational-number library for gnucash.
 

Data Structures

struct  gnc_numeric
 An rational-number type. More...
 

Variables

gint64 gnc_numeric::num
 
gint64 gnc_numeric::denom
 

Arguments Standard Arguments to most functions

Most of the gnc_numeric arithmetic functions take two arguments in addition to their numeric args: 'denom', which is the denominator to use in the output gnc_numeric object, and 'how'.

which describes how the arithmetic result is to be converted to that denominator. This combination of output denominator and rounding policy allows the results of financial and other rational computations to be properly rounded to the appropriate units.

Watch out: You must specify a rounding policy such as GNC_HOW_RND_NEVER, otherwise the fractional part of the input value might silently get discarded!

Valid values for denom are: GNC_DENOM_AUTO – compute denominator exactly integer n – Force the denominator of the result to be this integer GNC_DENOM_RECIPROCAL – Use 1/n as the denominator (???huh???)

Valid values for 'how' are bitwise combinations of zero or one "rounding instructions" with zero or one "denominator types". Valid rounding instructions are: GNC_HOW_RND_FLOOR GNC_HOW_RND_CEIL GNC_HOW_RND_TRUNC GNC_HOW_RND_PROMOTE GNC_HOW_RND_ROUND_HALF_DOWN GNC_HOW_RND_ROUND_HALF_UP GNC_HOW_RND_ROUND GNC_HOW_RND_NEVER

The denominator type specifies how to compute a denominator if GNC_DENOM_AUTO is specified as the 'denom'. Valid denominator types are: GNC_HOW_DENOM_EXACT GNC_HOW_DENOM_REDUCE GNC_HOW_DENOM_LCD GNC_HOW_DENOM_FIXED GNC_HOW_DENOM_SIGFIGS(N)

To use traditional rational-number operational semantics (all results are exact and are reduced to relatively-prime fractions) pass the argument GNC_DENOM_AUTO as 'denom' and GNC_HOW_DENOM_REDUCE| GNC_HOW_RND_NEVER as 'how'.

To enforce strict financial semantics (such that all operands must have the same denominator as each other and as the result), use GNC_DENOM_AUTO as 'denom' and GNC_HOW_DENOM_FIXED | GNC_HOW_RND_NEVER as 'how'.

enum  {
  GNC_HOW_RND_FLOOR = 0x01 , GNC_HOW_RND_CEIL = 0x02 , GNC_HOW_RND_TRUNC = 0x03 , GNC_HOW_RND_PROMOTE = 0x04 ,
  GNC_HOW_RND_ROUND_HALF_DOWN = 0x05 , GNC_HOW_RND_ROUND_HALF_UP = 0x06 , GNC_HOW_RND_ROUND = 0x07 , GNC_HOW_RND_NEVER = 0x08
}
 Rounding/Truncation modes for operations. More...
 
enum  {
  GNC_HOW_DENOM_EXACT = 0x10 , GNC_HOW_DENOM_REDUCE = 0x20 , GNC_HOW_DENOM_LCD = 0x30 , GNC_HOW_DENOM_FIXED = 0x40 ,
  GNC_HOW_DENOM_SIGFIG = 0x50
}
 How to compute a denominator, or'ed into the "how" field. More...
 
enum  GNCNumericErrorCode {
  GNC_ERROR_OK = 0 , GNC_ERROR_ARG = -1 , GNC_ERROR_OVERFLOW = -2 , GNC_ERROR_DENOM_DIFF = -3 ,
  GNC_ERROR_REMAINDER = -4
}
 Error codes. More...
 
#define GNC_NUMERIC_RND_MASK   0x0000000f
 bitmasks for HOW flags.
 
#define GNC_NUMERIC_DENOM_MASK   0x000000f0
 
#define GNC_NUMERIC_SIGFIGS_MASK   0x0000ff00
 
#define GNC_HOW_DENOM_SIGFIGS(n)   ( ((( n ) & 0xff) << 8) | GNC_HOW_DENOM_SIGFIG)
 Build a 'how' value that will generate a denominator that will keep at least n significant figures in the result.
 
#define GNC_HOW_GET_SIGFIGS(a)   ( (( a ) & 0xff00 ) >> 8)
 
#define GNC_DENOM_AUTO   0
 Values that can be passed as the 'denom' argument.
 

Constructors

gnc_numeric double_to_gnc_numeric (double n, gint64 denom, gint how)
 Convert a floating-point number to a gnc_numeric.
 
gnc_numeric gnc_numeric_from_string (const gchar *str)
 Read a gnc_numeric from str, skipping any leading whitespace.
 
gnc_numeric gnc_numeric_error (GNCNumericErrorCode error_code)
 Create a gnc_numeric object that signals the error condition noted by error_code, rather than a number.
 
const char * gnc_numeric_errorCode_to_string (GNCNumericErrorCode error_code)
 Returns a string representation of the given GNCNumericErrorCode.
 

Value Accessors

gdouble gnc_numeric_to_double (gnc_numeric n)
 Convert numeric to floating-point value.
 
gchar * gnc_numeric_to_string (gnc_numeric n)
 Convert to string.
 
gchar * gnc_num_dbg_to_string (gnc_numeric n)
 Convert to string.
 

Comparisons and Predicates

GNCNumericErrorCode gnc_numeric_check (gnc_numeric a)
 Check for error signal in value.
 
gint gnc_numeric_compare (gnc_numeric a, gnc_numeric b)
 Returns 1 if a>b, -1 if b>a, 0 if a == b

 
gboolean gnc_numeric_zero_p (gnc_numeric a)
 Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.
 
gboolean gnc_numeric_negative_p (gnc_numeric a)
 Returns 1 if a < 0, otherwise returns 0.
 
gboolean gnc_numeric_positive_p (gnc_numeric a)
 Returns 1 if a > 0, otherwise returns 0.
 
gboolean gnc_numeric_eq (gnc_numeric a, gnc_numeric b)
 Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and denominator)
 
gboolean gnc_numeric_equal (gnc_numeric a, gnc_numeric b)
 Equivalence predicate: Returns TRUE (1) if a and b represent the same number.
 
gint gnc_numeric_same (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Equivalence predicate: Convert both a and b to denom using the specified DENOM and method HOW, and compare numerators the results using gnc_numeric_equal.
 

Arithmetic Operations

gnc_numeric gnc_numeric_add (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Return a+b.
 
gnc_numeric gnc_numeric_sub (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Return a-b.
 
gnc_numeric gnc_numeric_mul (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Multiply a times b, returning the product.
 
gnc_numeric gnc_numeric_div (gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
 Division.
 
gnc_numeric gnc_numeric_neg (gnc_numeric a)
 Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.
 
gnc_numeric gnc_numeric_abs (gnc_numeric a)
 Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.
 

Change Denominator

gnc_numeric gnc_numeric_convert (gnc_numeric n, gint64 denom, gint how)
 Change the denominator of a gnc_numeric value to the specified denominator under standard arguments 'denom' and 'how'.
 
gnc_numeric gnc_numeric_reduce (gnc_numeric n)
 Return input after reducing it by Greater Common Factor (GCF) elimination.
 
gboolean gnc_numeric_to_decimal (gnc_numeric *a, guint8 *max_decimal_places)
 Attempt to convert the denominator to an exact power of ten without rounding.
 
gnc_numeric gnc_numeric_invert (gnc_numeric num)
 Invert a gnc_numeric.
 

GValue

GType gnc_numeric_get_type (void)
 
#define GNC_TYPE_NUMERIC   (gnc_numeric_get_type ())
 

Detailed Description

The 'Numeric' functions provide a way of working with rational numbers while maintaining strict control over rounding errors when adding rationals with different denominators.

The Numeric class is primarily used for working with monetary amounts, where the denominator typically represents the smallest fraction of the currency (e.g. pennies, centimes). The numeric class can handle any fraction (e.g. twelfth's) and is not limited to fractions that are powers of ten.

A 'Numeric' value represents a number in rational form, with a 64-bit integer as numerator and denominator. Rationals are ideal for many uses, such as performing exact, roundoff-error-free addition and multiplication, but 64-bit rationals do not have the dynamic range of floating point numbers.

Macro Definition Documentation

◆ GNC_DENOM_AUTO

#define GNC_DENOM_AUTO   0

Values that can be passed as the 'denom' argument.

The include a positive number n to be used as the denominator of the output value. Other possibilities include the list below: Compute an appropriate denominator automatically. Flags in the 'how' argument will specify how to compute the denominator.

Definition at line 245 of file gnc-numeric.h.

◆ GNC_HOW_DENOM_SIGFIGS

#define GNC_HOW_DENOM_SIGFIGS (   n)    ( ((( n ) & 0xff) << 8) | GNC_HOW_DENOM_SIGFIG)

Build a 'how' value that will generate a denominator that will keep at least n significant figures in the result.

Definition at line 217 of file gnc-numeric.h.

◆ GNC_HOW_GET_SIGFIGS

#define GNC_HOW_GET_SIGFIGS (   a)    ( (( a ) & 0xff00 ) >> 8)

Definition at line 218 of file gnc-numeric.h.

◆ GNC_NUMERIC_DENOM_MASK

#define GNC_NUMERIC_DENOM_MASK   0x000000f0

Definition at line 127 of file gnc-numeric.h.

◆ GNC_NUMERIC_RND_MASK

#define GNC_NUMERIC_RND_MASK   0x0000000f

bitmasks for HOW flags.

bits 8-15 of 'how' are reserved for the number of significant digits to use in the output with GNC_HOW_DENOM_SIGFIG

Definition at line 126 of file gnc-numeric.h.

◆ GNC_NUMERIC_SIGFIGS_MASK

#define GNC_NUMERIC_SIGFIGS_MASK   0x0000ff00

Definition at line 128 of file gnc-numeric.h.

◆ GNC_TYPE_NUMERIC

#define GNC_TYPE_NUMERIC   (gnc_numeric_get_type ())

Definition at line 489 of file gnc-numeric.h.

Enumeration Type Documentation

◆ anonymous enum

anonymous enum

Rounding/Truncation modes for operations.

Rounding instructions control how fractional parts in the specified denominator affect the result. For example, if a computed result is "3/4" but the specified denominator for the return value is 2, should the return value be "1/2" or "2/2"?

Watch out: You must specify a rounding policy such as GNC_HOW_RND_NEVER, otherwise the fractional part of the input value might silently get discarded!

Possible rounding instructions are:

Enumerator
GNC_HOW_RND_FLOOR 

Round toward -infinity.

GNC_HOW_RND_CEIL 

Round toward +infinity.

GNC_HOW_RND_TRUNC 

Truncate fractions (round toward zero)

GNC_HOW_RND_PROMOTE 

Promote fractions (round away from zero)

GNC_HOW_RND_ROUND_HALF_DOWN 

Round to the nearest integer, rounding toward zero when there are two equidistant nearest integers.

GNC_HOW_RND_ROUND_HALF_UP 

Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers.

GNC_HOW_RND_ROUND 

Use unbiased ("banker's") rounding.

This rounds to the nearest integer, and to the nearest even integer when there are two equidistant nearest integers. This is generally the one you should use for financial quantities.

GNC_HOW_RND_NEVER 

Never round at all, and signal an error if there is a fractional result in a computation.

Definition at line 143 of file gnc-numeric.h.

144{
146 GNC_HOW_RND_FLOOR = 0x01,
147
149 GNC_HOW_RND_CEIL = 0x02,
150
152 GNC_HOW_RND_TRUNC = 0x03,
153
155 GNC_HOW_RND_PROMOTE = 0x04,
156
161
166
172 GNC_HOW_RND_ROUND = 0x07,
173
177 GNC_HOW_RND_NEVER = 0x08
178};
@ GNC_HOW_RND_ROUND_HALF_UP
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
@ GNC_HOW_RND_ROUND_HALF_DOWN
Round to the nearest integer, rounding toward zero when there are two equidistant nearest integers.
@ GNC_HOW_RND_FLOOR
Round toward -infinity.
@ GNC_HOW_RND_PROMOTE
Promote fractions (round away from zero)
@ GNC_HOW_RND_NEVER
Never round at all, and signal an error if there is a fractional result in a computation.
@ GNC_HOW_RND_CEIL
Round toward +infinity.
@ GNC_HOW_RND_TRUNC
Truncate fractions (round toward zero)
@ GNC_HOW_RND_ROUND
Use unbiased ("banker's") rounding.

◆ anonymous enum

anonymous enum

How to compute a denominator, or'ed into the "how" field.

Enumerator
GNC_HOW_DENOM_EXACT 

Use any denominator which gives an exactly correct ratio of numerator to denominator.

Use EXACT when you do not wish to lose any information in the result but also do not want to spend any time finding the "best" denominator.

GNC_HOW_DENOM_REDUCE 

Reduce the result value by common factor elimination, using the smallest possible value for the denominator that keeps the correct ratio.

The numerator and denominator of the result are relatively prime.

GNC_HOW_DENOM_LCD 

Find the least common multiple of the arguments' denominators and use that as the denominator of the result.

GNC_HOW_DENOM_FIXED 

All arguments are required to have the same denominator, that denominator is to be used in the output, and an error is to be signaled if any argument has a different denominator.

GNC_HOW_DENOM_SIGFIG 

Round to the number of significant figures given in the rounding instructions by the GNC_HOW_DENOM_SIGFIGS () macro.

Definition at line 181 of file gnc-numeric.h.

182{
188 GNC_HOW_DENOM_EXACT = 0x10,
189
196
200 GNC_HOW_DENOM_LCD = 0x30,
201
206 GNC_HOW_DENOM_FIXED = 0x40,
207
212};
@ GNC_HOW_DENOM_REDUCE
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
@ GNC_HOW_DENOM_FIXED
All arguments are required to have the same denominator, that denominator is to be used in the output...
@ GNC_HOW_DENOM_LCD
Find the least common multiple of the arguments' denominators and use that as the denominator of the ...
@ GNC_HOW_DENOM_SIGFIG
Round to the number of significant figures given in the rounding instructions by the GNC_HOW_DENOM_SI...
@ GNC_HOW_DENOM_EXACT
Use any denominator which gives an exactly correct ratio of numerator to denominator.

◆ GNCNumericErrorCode

Error codes.

Enumerator
GNC_ERROR_OK 

No error.

GNC_ERROR_ARG 

Argument is not a valid number.

GNC_ERROR_OVERFLOW 

Intermediate result overflow.

GNC_ERROR_DENOM_DIFF 

GNC_HOW_DENOM_FIXED was specified, but argument denominators differed.


GNC_ERROR_REMAINDER 

GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator without a remainder.

Definition at line 221 of file gnc-numeric.h.

222{
223 GNC_ERROR_OK = 0,
224 GNC_ERROR_ARG = -1,
225 GNC_ERROR_OVERFLOW = -2,
229
GNCNumericErrorCode
Error codes.
@ GNC_ERROR_REMAINDER
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
@ GNC_ERROR_OVERFLOW
Intermediate result overflow.
@ GNC_ERROR_DENOM_DIFF
GNC_HOW_DENOM_FIXED was specified, but argument denominators differed.
@ GNC_ERROR_OK
No error.
@ GNC_ERROR_ARG
Argument is not a valid number.

Function Documentation

◆ double_to_gnc_numeric()

gnc_numeric double_to_gnc_numeric ( double  n,
gint64  denom,
gint  how 
)

Convert a floating-point number to a gnc_numeric.

Both 'denom' and 'how' are used as in arithmetic.

See also
Arguments
Parameters
nThe double value that is converted into a gnc_numeric
denomThe denominator of the gnc_numeric return value. If the 'how' argument contains the GNC_HOW_DENOM_SIGFIG flag, this value will be ignored. If GNC_DENOM_AUTO is given an appropriate power of ten will be used for the denominator (it may be reduced by rounding if appropriate).
howDescribes the rounding policy and output denominator. Watch out: You must specify a rounding policy such as GNC_HOW_RND_NEVER, otherwise the fractional part of the input value is silently discarded! Common values for 'how' are (GNC_HOW_DENOM_REDUCE|GNC_HOW_RND_NEVER) or (GNC_HOW_DENOM_FIXED|GNC_HOW_RND_NEVER).
Returns
The newly created gnc_numeric rational value.

Definition at line 1313 of file gnc-numeric.cpp.

1314{
1315 try
1316 {
1317 GncNumeric an(in);
1318 return convert(an, denom, how);
1319 }
1320 catch (const std::overflow_error& err)
1321 {
1322 PWARN("%s", err.what());
1324 }
1325 catch (const std::invalid_argument& err)
1326 {
1327 PWARN("%s", err.what());
1329 }
1330 catch (const std::underflow_error& err)
1331 {
1332 PWARN("%s", err.what());
1334 }
1335 catch (const std::domain_error& err)
1336 {
1337 PWARN("%s", err.what());
1339 }
1340}
The primary numeric class for representing amounts and values.
#define PWARN(format, args...)
Log a warning.
Definition qoflog.h:250
gnc_numeric gnc_numeric_error(GNCNumericErrorCode error_code)
Create a gnc_numeric object that signals the error condition noted by error_code, rather than a numbe...

◆ gnc_num_dbg_to_string()

gchar * gnc_num_dbg_to_string ( gnc_numeric  n)

Convert to string.

Uses a static, non-thread-safe buffer. For internal use only.

Definition at line 1388 of file gnc-numeric.cpp.

1389{
1390 static char buff[1000];
1391 static char *p = buff;
1392 static const size_t size = 50;
1393 int64_t tmpnum = n.num;
1394 int64_t tmpdenom = n.denom;
1395
1396 p += size;
1397 if ((size_t)(p - buff) > (sizeof(buff) - size))
1398 p = buff;
1399
1400 snprintf(p, size, "%" PRId64 "/%" PRId64, tmpnum, tmpdenom);
1401
1402 return p;
1403}

◆ gnc_numeric_abs()

gnc_numeric gnc_numeric_abs ( gnc_numeric  a)

Returns a newly created gnc_numeric that is the absolute value of the given gnc_numeric value.

For a given gnc_numeric "a/b" the returned value is "|a/b|".

Definition at line 1158 of file gnc-numeric.cpp.

1159{
1160 if (gnc_numeric_check(a))
1161 {
1163 }
1164 return gnc_numeric_create(ABS(a.num), a.denom);
1165}
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.

◆ gnc_numeric_add()

gnc_numeric gnc_numeric_add ( gnc_numeric  a,
gnc_numeric  b,
gint64  denom,
gint  how 
)

Return a+b.

Definition at line 928 of file gnc-numeric.cpp.

930{
932 {
934 }
935 try
936 {
937 denom = denom_lcd(a, b, denom, how);
938 if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
939 {
940 GncNumeric an (a), bn (b);
941 GncNumeric sum = an + bn;
942 return static_cast<gnc_numeric>(convert(sum, denom, how));
943 }
944 GncRational ar(a), br(b);
945 auto sum = ar + br;
946 if (denom == GNC_DENOM_AUTO &&
947 (how & GNC_NUMERIC_RND_MASK) != GNC_HOW_RND_NEVER)
948 return static_cast<gnc_numeric>(sum.round_to_numeric());
949 sum = convert(sum, denom, how);
950 if (sum.is_big() || !sum.valid())
952 return static_cast<gnc_numeric>(sum);
953 }
954 catch (const std::overflow_error& err)
955 {
956 PWARN("%s", err.what());
958 }
959 catch (const std::invalid_argument& err)
960 {
961 PWARN("%s", err.what());
963 }
964 catch (const std::underflow_error& err)
965 {
966 PWARN("%s", err.what());
968 }
969 catch (const std::domain_error& err)
970 {
971 PWARN("%s", err.what());
973 }
974}
Rational number class using GncInt128 for the numerator and denominator.
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
#define GNC_DENOM_AUTO
Values that can be passed as the 'denom' argument.

◆ gnc_numeric_check()

GNCNumericErrorCode gnc_numeric_check ( gnc_numeric  a)

Check for error signal in value.

Returns GNC_ERROR_OK (==0) if the number appears to be valid, otherwise it returns the type of error. Error values always have a denominator of zero.

Definition at line 737 of file gnc-numeric.cpp.

738{
739 if (G_LIKELY(in.denom != 0))
740 {
741 return GNC_ERROR_OK;
742 }
743 else if (in.num)
744 {
745 if ((0 < in.num) || (-4 > in.num))
746 {
747 in.num = (gint64) GNC_ERROR_OVERFLOW;
748 }
749 return (GNCNumericErrorCode) in.num;
750 }
751 else
752 {
753 return GNC_ERROR_ARG;
754 }
755}

◆ gnc_numeric_compare()

gint gnc_numeric_compare ( gnc_numeric  a,
gnc_numeric  b 
)

Returns 1 if a>b, -1 if b>a, 0 if a == b

Definition at line 837 of file gnc-numeric.cpp.

838{
840 {
841 return 0;
842 }
843
844 if (a.denom == b.denom)
845 {
846 if (a.num == b.num) return 0;
847 if (a.num > b.num) return 1;
848 return -1;
849 }
850
851 GncNumeric an (a), bn (b);
852
853 return an.cmp(bn);
854}

◆ gnc_numeric_div()

gnc_numeric gnc_numeric_div ( gnc_numeric  x,
gnc_numeric  y,
gint64  denom,
gint  how 
)

Division.

Note that division can overflow, in the following sense: if we write x=a/b and y=c/d then x/y = (a*d)/(b*c) If, after eliminating all common factors between the numerator (a*d) and the denominator (b*c), then if either the numerator and/or the denominator are still greater than 2^63, then the division has overflowed.

Definition at line 1089 of file gnc-numeric.cpp.

1091{
1093 {
1095 }
1096 try
1097 {
1098 denom = denom_lcd(a, b, denom, how);
1099 if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
1100 {
1101 GncNumeric an (a), bn (b);
1102 auto quot = an / bn;
1103 return static_cast<gnc_numeric>(convert(quot, denom, how));
1104 }
1105 GncRational ar(a), br(b);
1106 auto quot = ar / br;
1107 if (denom == GNC_DENOM_AUTO &&
1108 (how & GNC_NUMERIC_RND_MASK) != GNC_HOW_RND_NEVER)
1109 return static_cast<gnc_numeric>(quot.round_to_numeric());
1110 quot = static_cast<gnc_numeric>(convert(quot, denom, how));
1111 if (quot.is_big() || !quot.valid())
1113 return static_cast<gnc_numeric>(quot);
1114 }
1115 catch (const std::overflow_error& err)
1116 {
1117 PWARN("%s", err.what());
1119 }
1120 catch (const std::invalid_argument& err)
1121 {
1122 PWARN("%s", err.what());
1124 }
1125 catch (const std::underflow_error& err) //Divide by zero
1126 {
1127 PWARN("%s", err.what());
1129 }
1130 catch (const std::domain_error& err)
1131 {
1132 PWARN("%s", err.what());
1134 }
1135}

◆ gnc_numeric_eq()

gboolean gnc_numeric_eq ( gnc_numeric  a,
gnc_numeric  b 
)

Equivalence predicate: Returns TRUE (1) if a and b are exactly the same (have the same numerator and denominator)

Definition at line 862 of file gnc-numeric.cpp.

863{
864 return ((a.num == b.num) && (a.denom == b.denom));
865}

◆ gnc_numeric_equal()

gboolean gnc_numeric_equal ( gnc_numeric  a,
gnc_numeric  b 
)

Equivalence predicate: Returns TRUE (1) if a and b represent the same number.

That is, return TRUE if the ratios, when reduced by eliminating common factors, are identical.

Definition at line 873 of file gnc-numeric.cpp.

874{
875 if (gnc_numeric_check(a))
876 {
877 /* a is not a valid number, check b */
878 if (gnc_numeric_check(b))
879 /* Both invalid, consider them equal */
880 return TRUE;
881 else
882 /* a invalid, b valid */
883 return FALSE;
884 }
885 if (gnc_numeric_check(b))
886 /* a valid, b invalid */
887 return FALSE;
888
889 return gnc_numeric_compare (a, b) == 0;
890}
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b

◆ gnc_numeric_error()

gnc_numeric gnc_numeric_error ( GNCNumericErrorCode  error_code)

Create a gnc_numeric object that signals the error condition noted by error_code, rather than a number.

Definition at line 1364 of file gnc-numeric.cpp.

1365{
1366 return gnc_numeric_create(error_code, 0LL);
1367}

◆ gnc_numeric_errorCode_to_string()

const char * gnc_numeric_errorCode_to_string ( GNCNumericErrorCode  error_code)

Returns a string representation of the given GNCNumericErrorCode.

Definition at line 1511 of file gnc-numeric.cpp.

1512{
1513 switch (error_code)
1514 {
1515 case GNC_ERROR_OK:
1516 return "GNC_ERROR_OK";
1517 case GNC_ERROR_ARG:
1518 return "GNC_ERROR_ARG";
1519 case GNC_ERROR_OVERFLOW:
1520 return "GNC_ERROR_OVERFLOW";
1522 return "GNC_ERROR_DENOM_DIFF";
1524 return "GNC_ERROR_REMAINDER";
1525 default:
1526 return "<unknown>";
1527 }
1528}

◆ gnc_numeric_from_string()

gnc_numeric gnc_numeric_from_string ( const gchar *  str)

Read a gnc_numeric from str, skipping any leading whitespace.

Returns the resulting gnc_numeric. Return GNC_ERROR_ARG on error.

Definition at line 1406 of file gnc-numeric.cpp.

1407{
1408 if (!str)
1410
1411 // the default gnc_numeric string format is "num/denom", whereby
1412 // the denom must be >= 1. this speedily parses it. this also
1413 // parses "num" as num/1.
1414 if (auto res = fast_numeral_rational (str))
1415 return *res;
1416
1417 try
1418 {
1419 return GncNumeric (str);
1420 }
1421 catch (const std::exception& err)
1422 {
1423 PWARN("%s", err.what());
1425 }
1426}

◆ gnc_numeric_invert()

gnc_numeric gnc_numeric_invert ( gnc_numeric  num)

Invert a gnc_numeric.

Much faster than dividing 1 by it.

Parameters
numThe number to be inverted
Returns
a gnc_numeric that is the inverse of num

Definition at line 1275 of file gnc-numeric.cpp.

1276{
1277 if (num.num == 0)
1278 return gnc_numeric_zero();
1279 try
1280 {
1281 return static_cast<gnc_numeric>(GncNumeric(num).inv());
1282 }
1283 catch (const std::overflow_error& err)
1284 {
1285 PWARN("%s", err.what());
1287 }
1288 catch (const std::invalid_argument& err)
1289 {
1290 PWARN("%s", err.what());
1292 }
1293 catch (const std::underflow_error& err)
1294 {
1295 PWARN("%s", err.what());
1297 }
1298 catch (const std::domain_error& err)
1299 {
1300 PWARN("%s", err.what());
1302 }
1303}
GncNumeric inv() const noexcept

◆ gnc_numeric_mul()

gnc_numeric gnc_numeric_mul ( gnc_numeric  a,
gnc_numeric  b,
gint64  denom,
gint  how 
)

Multiply a times b, returning the product.

An overflow may occur if the result of the multiplication can't be represented as a ratio of 64-bit int's after removing common factors.

Definition at line 1034 of file gnc-numeric.cpp.

1036{
1038 {
1040 }
1041
1042 try
1043 {
1044 denom = denom_lcd(a, b, denom, how);
1045 if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
1046 {
1047 GncNumeric an (a), bn (b);
1048 auto prod = an * bn;
1049 return static_cast<gnc_numeric>(convert(prod, denom, how));
1050 }
1051 GncRational ar(a), br(b);
1052 auto prod = ar * br;
1053 if (denom == GNC_DENOM_AUTO &&
1054 (how & GNC_NUMERIC_RND_MASK) != GNC_HOW_RND_NEVER)
1055 return static_cast<gnc_numeric>(prod.round_to_numeric());
1056 prod = convert(prod, denom, how);
1057 if (prod.is_big() || !prod.valid())
1059 return static_cast<gnc_numeric>(prod);
1060 }
1061 catch (const std::overflow_error& err)
1062 {
1063 PWARN("%s", err.what());
1065 }
1066 catch (const std::invalid_argument& err)
1067 {
1068 PWARN("%s", err.what());
1070 }
1071 catch (const std::underflow_error& err)
1072 {
1073 PWARN("%s", err.what());
1075 }
1076 catch (const std::domain_error& err)
1077 {
1078 PWARN("%s", err.what());
1080 }
1081}

◆ gnc_numeric_neg()

gnc_numeric gnc_numeric_neg ( gnc_numeric  a)

Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value.

For a given gnc_numeric "a/b" the returned value is "-a/b".

Definition at line 1143 of file gnc-numeric.cpp.

1144{
1145 if (gnc_numeric_check(a))
1146 {
1148 }
1149 return gnc_numeric_create(- a.num, a.denom);
1150}

◆ gnc_numeric_negative_p()

gboolean gnc_numeric_negative_p ( gnc_numeric  a)

Returns 1 if a < 0, otherwise returns 0.

Definition at line 787 of file gnc-numeric.cpp.

788{
789 if (gnc_numeric_check(a))
790 {
791 return 0;
792 }
793 else
794 {
795 if ((a.num < 0) && (a.denom != 0))
796 {
797 return 1;
798 }
799 else
800 {
801 return 0;
802 }
803 }
804}

◆ gnc_numeric_positive_p()

gboolean gnc_numeric_positive_p ( gnc_numeric  a)

Returns 1 if a > 0, otherwise returns 0.

Definition at line 811 of file gnc-numeric.cpp.

812{
813 if (gnc_numeric_check(a))
814 {
815 return 0;
816 }
817 else
818 {
819 if ((a.num > 0) && (a.denom != 0))
820 {
821 return 1;
822 }
823 else
824 {
825 return 0;
826 }
827 }
828}

◆ gnc_numeric_reduce()

gnc_numeric gnc_numeric_reduce ( gnc_numeric  n)

Return input after reducing it by Greater Common Factor (GCF) elimination.

Definition at line 1207 of file gnc-numeric.cpp.

1208{
1209 if (gnc_numeric_check(in))
1210 {
1212 }
1213
1214 if (in.denom < 0) /* Negative denoms multiply num, can't be reduced. */
1215 return in;
1216 try
1217 {
1218 GncNumeric an (in);
1219 return static_cast<gnc_numeric>(an.reduce());
1220 }
1221 catch (const std::overflow_error& err)
1222 {
1223 PWARN("%s", err.what());
1225 }
1226 catch (const std::invalid_argument& err)
1227 {
1228 PWARN("%s", err.what());
1230 }
1231 catch (const std::underflow_error& err)
1232 {
1233 PWARN("%s", err.what());
1235 }
1236 catch (const std::domain_error& err)
1237 {
1238 PWARN("%s", err.what());
1240 }
1241}

◆ gnc_numeric_same()

gint gnc_numeric_same ( gnc_numeric  a,
gnc_numeric  b,
gint64  denom,
gint  how 
)

Equivalence predicate: Convert both a and b to denom using the specified DENOM and method HOW, and compare numerators the results using gnc_numeric_equal.

For example, if a == 7/16 and b == 3/4, gnc_numeric_same(a, b, 2, GNC_HOW_RND_TRUNC) == 1 because both 7/16 and 3/4 round to 1/2 under truncation. However, gnc_numeric_same(a, b, 2, GNC_HOW_RND_ROUND) == 0 because 7/16 rounds to 1/2 under unbiased rounding but 3/4 rounds to 2/2.

Definition at line 900 of file gnc-numeric.cpp.

902{
903 gnc_numeric aconv, bconv;
904
905 aconv = gnc_numeric_convert(a, denom, how);
906 bconv = gnc_numeric_convert(b, denom, how);
907
908 return(gnc_numeric_equal(aconv, bconv));
909}
gboolean gnc_numeric_equal(gnc_numeric a, gnc_numeric b)
Equivalence predicate: Returns TRUE (1) if a and b represent the same number.

◆ gnc_numeric_sub()

gnc_numeric gnc_numeric_sub ( gnc_numeric  a,
gnc_numeric  b,
gint64  denom,
gint  how 
)

Return a-b.

Definition at line 981 of file gnc-numeric.cpp.

983{
985 {
987 }
988 try
989 {
990 denom = denom_lcd(a, b, denom, how);
991 if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
992 {
993 GncNumeric an (a), bn (b);
994 auto sum = an - bn;
995 return static_cast<gnc_numeric>(convert(sum, denom, how));
996 }
997 GncRational ar(a), br(b);
998 auto sum = ar - br;
999 if (denom == GNC_DENOM_AUTO &&
1000 (how & GNC_NUMERIC_RND_MASK) != GNC_HOW_RND_NEVER)
1001 return static_cast<gnc_numeric>(sum.round_to_numeric());
1002 sum = convert(sum, denom, how);
1003 if (sum.is_big() || !sum.valid())
1005 return static_cast<gnc_numeric>(sum);
1006 }
1007 catch (const std::overflow_error& err)
1008 {
1009 PWARN("%s", err.what());
1011 }
1012 catch (const std::invalid_argument& err)
1013 {
1014 PWARN("%s", err.what());
1016 }
1017 catch (const std::underflow_error& err)
1018 {
1019 PWARN("%s", err.what());
1021 }
1022 catch (const std::domain_error& err)
1023 {
1024 PWARN("%s", err.what());
1026 }
1027}

◆ gnc_numeric_to_decimal()

gboolean gnc_numeric_to_decimal ( gnc_numeric *  a,
guint8 *  max_decimal_places 
)

Attempt to convert the denominator to an exact power of ten without rounding.

Parameters
athe ::gnc_numeric value to convert
max_decimal_placesthe number of decimal places of the converted value. This parameter may be NULL.
Returns
TRUE if a has been converted or was already decimal. Otherwise, FALSE is returned and a and max_decimal_places remain unchanged.

Definition at line 1254 of file gnc-numeric.cpp.

1255{
1256 int max_places = max_decimal_places == NULL ? max_leg_digits :
1257 *max_decimal_places;
1258 if (a->num == 0) return TRUE;
1259 try
1260 {
1261 GncNumeric an (*a);
1262 auto bn = an.to_decimal(max_places);
1263 *a = static_cast<gnc_numeric>(bn);
1264 return TRUE;
1265 }
1266 catch (const std::exception& err)
1267 {
1268 PINFO ("%s", err.what());
1269 return FALSE;
1270 }
1271}
#define PINFO(format, args...)
Print an informational note.
Definition qoflog.h:256

◆ gnc_numeric_to_double()

gdouble gnc_numeric_to_double ( gnc_numeric  n)

Convert numeric to floating-point value.

Definition at line 1347 of file gnc-numeric.cpp.

1348{
1349 if (in.denom > 0)
1350 {
1351 return (double)in.num / (double)in.denom;
1352 }
1353 else
1354 {
1355 return (double)(in.num * -in.denom);
1356 }
1357}

◆ gnc_numeric_to_string()

gchar * gnc_numeric_to_string ( gnc_numeric  n)

Convert to string.

The returned buffer is to be g_free'd by the caller (it was allocated through g_strdup)

Definition at line 1376 of file gnc-numeric.cpp.

1377{
1378 char *result;
1379 int64_t tmpnum = n.num;
1380 int64_t tmpdenom = n.denom;
1381
1382 result = g_strdup_printf("%" PRId64 "/%" PRId64, tmpnum, tmpdenom);
1383
1384 return result;
1385}

◆ gnc_numeric_zero_p()

gboolean gnc_numeric_zero_p ( gnc_numeric  a)

Returns 1 if the given gnc_numeric is 0 (zero), else returns 0.

Definition at line 763 of file gnc-numeric.cpp.

764{
765 if (gnc_numeric_check(a))
766 {
767 return 0;
768 }
769 else
770 {
771 if ((a.num == 0) && (a.denom != 0))
772 {
773 return 1;
774 }
775 else
776 {
777 return 0;
778 }
779 }
780}

Variable Documentation

◆ denom

gint64 gnc_numeric::denom

Definition at line 61 of file gnc-numeric.h.

◆ num

gint64 gnc_numeric::num

Definition at line 60 of file gnc-numeric.h.