GnuCash  5.6-133-gc519490283+
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. More...
 
#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. More...
 

Constructors

gnc_numeric double_to_gnc_numeric (double n, gint64 denom, gint how)
 Convert a floating-point number to a gnc_numeric. More...
 
gnc_numeric gnc_numeric_from_string (const gchar *str)
 Read a gnc_numeric from str, skipping any leading whitespace. More...
 
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. More...
 
gchar * gnc_numeric_to_string (gnc_numeric n)
 Convert to string. More...
 
gchar * gnc_num_dbg_to_string (gnc_numeric n)
 Convert to string. More...
 

Comparisons and Predicates

GNCNumericErrorCode gnc_numeric_check (gnc_numeric a)
 Check for error signal in value. More...
 
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. More...
 
gboolean gnc_numeric_negative_p (gnc_numeric a)
 Returns 1 if a < 0, otherwise returns 0. More...
 
gboolean gnc_numeric_positive_p (gnc_numeric a)
 Returns 1 if a > 0, otherwise returns 0. More...
 
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. More...
 
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. More...
 

Arithmetic Operations

gnc_numeric gnc_numeric_add (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Return a+b. More...
 
gnc_numeric gnc_numeric_sub (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Return a-b. More...
 
gnc_numeric gnc_numeric_mul (gnc_numeric a, gnc_numeric b, gint64 denom, gint how)
 Multiply a times b, returning the product. More...
 
gnc_numeric gnc_numeric_div (gnc_numeric x, gnc_numeric y, gint64 denom, gint how)
 Division. More...
 
gnc_numeric gnc_numeric_neg (gnc_numeric a)
 Returns a newly created gnc_numeric that is the negative of the given gnc_numeric value. More...
 
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. More...
 

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. More...
 
gnc_numeric gnc_numeric_invert (gnc_numeric num)
 Invert a gnc_numeric. More...
 

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.

See gnc_numeric Example

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 247 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 128 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 145 of file gnc-numeric.h.

146 {
148  GNC_HOW_RND_FLOOR = 0x01,
149 
151  GNC_HOW_RND_CEIL = 0x02,
152 
154  GNC_HOW_RND_TRUNC = 0x03,
155 
157  GNC_HOW_RND_PROMOTE = 0x04,
158 
163 
168 
174  GNC_HOW_RND_ROUND = 0x07,
175 
179  GNC_HOW_RND_NEVER = 0x08
180 };
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:179
Round toward +infinity.
Definition: gnc-numeric.h:151
Round toward -infinity.
Definition: gnc-numeric.h:148
Truncate fractions (round toward zero)
Definition: gnc-numeric.h:154
Promote fractions (round away from zero)
Definition: gnc-numeric.h:157
Round to the nearest integer, rounding toward zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:162
Round to the nearest integer, rounding away from zero when there are two equidistant nearest integers...
Definition: gnc-numeric.h:167
Use unbiased ("banker&#39;s") rounding.
Definition: gnc-numeric.h:174

◆ 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 183 of file gnc-numeric.h.

184 {
190  GNC_HOW_DENOM_EXACT = 0x10,
191 
197  GNC_HOW_DENOM_REDUCE = 0x20,
198 
202  GNC_HOW_DENOM_LCD = 0x30,
203 
208  GNC_HOW_DENOM_FIXED = 0x40,
209 
213  GNC_HOW_DENOM_SIGFIG = 0x50
214 };
All arguments are required to have the same denominator, that denominator is to be used in the output...
Definition: gnc-numeric.h:208
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:190
Find the least common multiple of the arguments&#39; denominators and use that as the denominator of the ...
Definition: gnc-numeric.h:202
Reduce the result value by common factor elimination, using the smallest possible value for the denom...
Definition: gnc-numeric.h:197
Round to the number of significant figures given in the rounding instructions by the GNC_HOW_DENOM_SI...
Definition: gnc-numeric.h:213

◆ 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 223 of file gnc-numeric.h.

224 {
225  GNC_ERROR_OK = 0,
226  GNC_ERROR_ARG = -1,
227  GNC_ERROR_OVERFLOW = -2,
231 
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
GNCNumericErrorCode
Error codes.
Definition: gnc-numeric.h:223
Intermediate result overflow.
Definition: gnc-numeric.h:227
Argument is not a valid number.
Definition: gnc-numeric.h:226
GNC_HOW_DENOM_FIXED was specified, but argument denominators differed.
Definition: gnc-numeric.h:230
No error.
Definition: gnc-numeric.h:225

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 1265 of file gnc-numeric.cpp.

1266 {
1267  try
1268  {
1269  GncNumeric an(in);
1270  return convert(an, denom, how);
1271  }
1272  catch (const std::overflow_error& err)
1273  {
1274  PWARN("%s", err.what());
1276  }
1277  catch (const std::invalid_argument& err)
1278  {
1279  PWARN("%s", err.what());
1281  }
1282  catch (const std::underflow_error& err)
1283  {
1284  PWARN("%s", err.what());
1286  }
1287  catch (const std::domain_error& err)
1288  {
1289  PWARN("%s", err.what());
1291  }
1292 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:227
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226

◆ 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 1340 of file gnc-numeric.cpp.

1341 {
1342  static char buff[1000];
1343  static char *p = buff;
1344  static const size_t size = 50;
1345  int64_t tmpnum = n.num;
1346  int64_t tmpdenom = n.denom;
1347 
1348  p += size;
1349  if ((size_t)(p - buff) > (sizeof(buff) - size))
1350  p = buff;
1351 
1352  snprintf(p, size, "%" PRId64 "/%" PRId64, tmpnum, tmpdenom);
1353 
1354  return p;
1355 }

◆ 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 1110 of file gnc-numeric.cpp.

1111 {
1112  if (gnc_numeric_check(a))
1113  {
1115  }
1116  return gnc_numeric_create(ABS(a.num), a.denom);
1117 }
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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
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 880 of file gnc-numeric.cpp.

882 {
884  {
886  }
887  try
888  {
889  denom = denom_lcd(a, b, denom, how);
890  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
891  {
892  GncNumeric an (a), bn (b);
893  GncNumeric sum = an + bn;
894  return static_cast<gnc_numeric>(convert(sum, denom, how));
895  }
896  GncRational ar(a), br(b);
897  auto sum = ar + br;
898  if (denom == GNC_DENOM_AUTO &&
900  return static_cast<gnc_numeric>(sum.round_to_numeric());
901  sum = convert(sum, denom, how);
902  if (sum.is_big() || !sum.valid())
904  return static_cast<gnc_numeric>(sum);
905  }
906  catch (const std::overflow_error& err)
907  {
908  PWARN("%s", err.what());
910  }
911  catch (const std::invalid_argument& err)
912  {
913  PWARN("%s", err.what());
915  }
916  catch (const std::underflow_error& err)
917  {
918  PWARN("%s", err.what());
920  }
921  catch (const std::domain_error& err)
922  {
923  PWARN("%s", err.what());
925  }
926 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:179
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:227
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:190
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
Rational number class using GncInt128 for the numerator and denominator.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:247
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:128

◆ 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 689 of file gnc-numeric.cpp.

690 {
691  if (G_LIKELY(in.denom != 0))
692  {
693  return GNC_ERROR_OK;
694  }
695  else if (in.num)
696  {
697  if ((0 < in.num) || (-4 > in.num))
698  {
699  in.num = (gint64) GNC_ERROR_OVERFLOW;
700  }
701  return (GNCNumericErrorCode) in.num;
702  }
703  else
704  {
705  return GNC_ERROR_ARG;
706  }
707 }
GNCNumericErrorCode
Error codes.
Definition: gnc-numeric.h:223
Intermediate result overflow.
Definition: gnc-numeric.h:227
Argument is not a valid number.
Definition: gnc-numeric.h:226
No error.
Definition: gnc-numeric.h:225

◆ 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 1041 of file gnc-numeric.cpp.

1043 {
1044  if (gnc_numeric_check(a) || gnc_numeric_check(b))
1045  {
1047  }
1048  try
1049  {
1050  denom = denom_lcd(a, b, denom, how);
1051  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
1052  {
1053  GncNumeric an (a), bn (b);
1054  auto quot = an / bn;
1055  return static_cast<gnc_numeric>(convert(quot, denom, how));
1056  }
1057  GncRational ar(a), br(b);
1058  auto quot = ar / br;
1059  if (denom == GNC_DENOM_AUTO &&
1061  return static_cast<gnc_numeric>(quot.round_to_numeric());
1062  quot = static_cast<gnc_numeric>(convert(quot, denom, how));
1063  if (quot.is_big() || !quot.valid())
1065  return static_cast<gnc_numeric>(quot);
1066  }
1067  catch (const std::overflow_error& err)
1068  {
1069  PWARN("%s", err.what());
1071  }
1072  catch (const std::invalid_argument& err)
1073  {
1074  PWARN("%s", err.what());
1076  }
1077  catch (const std::underflow_error& err) //Divide by zero
1078  {
1079  PWARN("%s", err.what());
1081  }
1082  catch (const std::domain_error& err)
1083  {
1084  PWARN("%s", err.what());
1086  }
1087 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:179
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:227
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:190
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
Rational number class using GncInt128 for the numerator and denominator.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:247
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:128

◆ 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 825 of file gnc-numeric.cpp.

826 {
827  if (gnc_numeric_check(a))
828  {
829  /* a is not a valid number, check b */
830  if (gnc_numeric_check(b))
831  /* Both invalid, consider them equal */
832  return TRUE;
833  else
834  /* a invalid, b valid */
835  return FALSE;
836  }
837  if (gnc_numeric_check(b))
838  /* a valid, b invalid */
839  return FALSE;
840 
841  return gnc_numeric_compare (a, b) == 0;
842 }
int gnc_numeric_compare(gnc_numeric a, gnc_numeric b)
Returns 1 if a>b, -1 if b>a, 0 if a == b.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.

◆ 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 1358 of file gnc-numeric.cpp.

1359 {
1360  if (!str)
1362 
1363  // the default gnc_numeric string format is "num/denom", whereby
1364  // the denom must be >= 1. this speedily parses it. this also
1365  // parses "num" as num/1.
1366  if (auto res = fast_numeral_rational (str))
1367  return *res;
1368 
1369  try
1370  {
1371  return GncNumeric (str);
1372  }
1373  catch (const std::exception& err)
1374  {
1375  PWARN("%s", err.what());
1377  }
1378 }
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226

◆ 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 1227 of file gnc-numeric.cpp.

1228 {
1229  if (num.num == 0)
1230  return gnc_numeric_zero();
1231  try
1232  {
1233  return static_cast<gnc_numeric>(GncNumeric(num).inv());
1234  }
1235  catch (const std::overflow_error& err)
1236  {
1237  PWARN("%s", err.what());
1239  }
1240  catch (const std::invalid_argument& err)
1241  {
1242  PWARN("%s", err.what());
1244  }
1245  catch (const std::underflow_error& err)
1246  {
1247  PWARN("%s", err.what());
1249  }
1250  catch (const std::domain_error& err)
1251  {
1252  PWARN("%s", err.what());
1254  }
1255 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:227
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
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 986 of file gnc-numeric.cpp.

988 {
990  {
992  }
993 
994  try
995  {
996  denom = denom_lcd(a, b, denom, how);
997  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
998  {
999  GncNumeric an (a), bn (b);
1000  auto prod = an * bn;
1001  return static_cast<gnc_numeric>(convert(prod, denom, how));
1002  }
1003  GncRational ar(a), br(b);
1004  auto prod = ar * br;
1005  if (denom == GNC_DENOM_AUTO &&
1007  return static_cast<gnc_numeric>(prod.round_to_numeric());
1008  prod = convert(prod, denom, how);
1009  if (prod.is_big() || !prod.valid())
1011  return static_cast<gnc_numeric>(prod);
1012  }
1013  catch (const std::overflow_error& err)
1014  {
1015  PWARN("%s", err.what());
1017  }
1018  catch (const std::invalid_argument& err)
1019  {
1020  PWARN("%s", err.what());
1022  }
1023  catch (const std::underflow_error& err)
1024  {
1025  PWARN("%s", err.what());
1027  }
1028  catch (const std::domain_error& err)
1029  {
1030  PWARN("%s", err.what());
1032  }
1033 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:179
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:227
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:190
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
Rational number class using GncInt128 for the numerator and denominator.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:247
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:128

◆ 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 1095 of file gnc-numeric.cpp.

1096 {
1097  if (gnc_numeric_check(a))
1098  {
1100  }
1101  return gnc_numeric_create(- a.num, a.denom);
1102 }
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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.

◆ gnc_numeric_negative_p()

gboolean gnc_numeric_negative_p ( gnc_numeric  a)

Returns 1 if a < 0, otherwise returns 0.

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

740 {
741  if (gnc_numeric_check(a))
742  {
743  return 0;
744  }
745  else
746  {
747  if ((a.num < 0) && (a.denom != 0))
748  {
749  return 1;
750  }
751  else
752  {
753  return 0;
754  }
755  }
756 }
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.

◆ gnc_numeric_positive_p()

gboolean gnc_numeric_positive_p ( gnc_numeric  a)

Returns 1 if a > 0, otherwise 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 }
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.

◆ 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 852 of file gnc-numeric.cpp.

854 {
855  gnc_numeric aconv, bconv;
856 
857  aconv = gnc_numeric_convert(a, denom, how);
858  bconv = gnc_numeric_convert(b, denom, how);
859 
860  return(gnc_numeric_equal(aconv, bconv));
861 }
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 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 &#39;...

◆ gnc_numeric_sub()

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

Return a-b.

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

935 {
937  {
939  }
940  try
941  {
942  denom = denom_lcd(a, b, denom, how);
943  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
944  {
945  GncNumeric an (a), bn (b);
946  auto sum = an - bn;
947  return static_cast<gnc_numeric>(convert(sum, denom, how));
948  }
949  GncRational ar(a), br(b);
950  auto sum = ar - br;
951  if (denom == GNC_DENOM_AUTO &&
953  return static_cast<gnc_numeric>(sum.round_to_numeric());
954  sum = convert(sum, denom, how);
955  if (sum.is_big() || !sum.valid())
957  return static_cast<gnc_numeric>(sum);
958  }
959  catch (const std::overflow_error& err)
960  {
961  PWARN("%s", err.what());
963  }
964  catch (const std::invalid_argument& err)
965  {
966  PWARN("%s", err.what());
968  }
969  catch (const std::underflow_error& err)
970  {
971  PWARN("%s", err.what());
973  }
974  catch (const std::domain_error& err)
975  {
976  PWARN("%s", err.what());
978  }
979 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:234
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:179
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:227
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:190
#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...
Argument is not a valid number.
Definition: gnc-numeric.h:226
Rational number class using GncInt128 for the numerator and denominator.
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.
#define GNC_DENOM_AUTO
Values that can be passed as the &#39;denom&#39; argument.
Definition: gnc-numeric.h:247
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:128

◆ 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 1206 of file gnc-numeric.cpp.

1207 {
1208  int max_places = max_decimal_places == NULL ? max_leg_digits :
1209  *max_decimal_places;
1210  if (a->num == 0) return TRUE;
1211  try
1212  {
1213  GncNumeric an (*a);
1214  auto bn = an.to_decimal(max_places);
1215  *a = static_cast<gnc_numeric>(bn);
1216  return TRUE;
1217  }
1218  catch (const std::exception& err)
1219  {
1220  PINFO ("%s", err.what());
1221  return FALSE;
1222  }
1223 }
#define PINFO(format, args...)
Print an informational note.
Definition: qoflog.h:256
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59

◆ gnc_numeric_to_double()

gdouble gnc_numeric_to_double ( gnc_numeric  n)

Convert numeric to floating-point value.

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

1300 {
1301  if (in.denom > 0)
1302  {
1303  return (double)in.num / (double)in.denom;
1304  }
1305  else
1306  {
1307  return (double)(in.num * -in.denom);
1308  }
1309 }

◆ 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 1328 of file gnc-numeric.cpp.

1329 {
1330  char *result;
1331  int64_t tmpnum = n.num;
1332  int64_t tmpdenom = n.denom;
1333 
1334  result = g_strdup_printf("%" PRId64 "/%" PRId64, tmpnum, tmpdenom);
1335 
1336  return result;
1337 }

◆ 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 715 of file gnc-numeric.cpp.

716 {
717  if (gnc_numeric_check(a))
718  {
719  return 0;
720  }
721  else
722  {
723  if ((a.num == 0) && (a.denom != 0))
724  {
725  return 1;
726  }
727  else
728  {
729  return 0;
730  }
731  }
732 }
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.