GnuCash  4.8a-132-gcdaeb421d+
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...
 
gboolean string_to_gnc_numeric (const gchar *str, gnc_numeric *n)
 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 246 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 127 of file gnc-numeric.h.

Enumeration Type Documentation

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

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

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

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

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

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

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

1139 {
1140  try
1141  {
1142  GncNumeric an(in);
1143  return convert(an, denom, how);
1144  }
1145  catch (const std::overflow_error& err)
1146  {
1147  PWARN("%s", err.what());
1149  }
1150  catch (const std::invalid_argument& err)
1151  {
1152  PWARN("%s", err.what());
1154  }
1155  catch (const std::underflow_error& err)
1156  {
1157  PWARN("%s", err.what());
1159  }
1160  catch (const std::domain_error& err)
1161  {
1162  PWARN("%s", err.what());
1164  }
1165 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:233
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:226
#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:225

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

1214 {
1215  static char buff[1000];
1216  static char *p = buff;
1217  gint64 tmpnum = n.num;
1218  gint64 tmpdenom = n.denom;
1219 
1220  p += 100;
1221  if (p - buff >= 1000) p = buff;
1222 
1223  sprintf(p, "%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, tmpnum, tmpdenom);
1224 
1225  return p;
1226 }

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

984 {
985  if (gnc_numeric_check(a))
986  {
988  }
989  return gnc_numeric_create(ABS(a.num), a.denom);
990 }
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:225
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 752 of file gnc-numeric.cpp.

754 {
756  {
758  }
759  try
760  {
761  denom = denom_lcd(a, b, denom, how);
762  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
763  {
764  GncNumeric an (a), bn (b);
765  GncNumeric sum = an + bn;
766  return static_cast<gnc_numeric>(convert(sum, denom, how));
767  }
768  GncRational ar(a), br(b);
769  auto sum = ar + br;
770  if (denom == GNC_DENOM_AUTO &&
772  return static_cast<gnc_numeric>(sum.round_to_numeric());
773  sum = convert(sum, denom, how);
774  if (sum.is_big() || !sum.valid())
776  return static_cast<gnc_numeric>(sum);
777  }
778  catch (const std::overflow_error& err)
779  {
780  PWARN("%s", err.what());
782  }
783  catch (const std::invalid_argument& err)
784  {
785  PWARN("%s", err.what());
787  }
788  catch (const std::underflow_error& err)
789  {
790  PWARN("%s", err.what());
792  }
793  catch (const std::domain_error& err)
794  {
795  PWARN("%s", err.what());
797  }
798 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:233
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:189
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:226
#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:225
Rational number class using GncInt128 for the numerator and denominator.
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:178
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:246
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:127

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

560 {
561  if (G_LIKELY(in.denom != 0))
562  {
563  return GNC_ERROR_OK;
564  }
565  else if (in.num)
566  {
567  if ((0 < in.num) || (-4 > in.num))
568  {
569  in.num = (gint64) GNC_ERROR_OVERFLOW;
570  }
571  return (GNCNumericErrorCode) in.num;
572  }
573  else
574  {
575  return GNC_ERROR_ARG;
576  }
577 }
GNCNumericErrorCode
Error codes.
Definition: gnc-numeric.h:222
Intermediate result overflow.
Definition: gnc-numeric.h:226
Argument is not a valid number.
Definition: gnc-numeric.h:225
No error.
Definition: gnc-numeric.h:224

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

916 {
918  {
920  }
921  try
922  {
923  denom = denom_lcd(a, b, denom, how);
924  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
925  {
926  GncNumeric an (a), bn (b);
927  auto quot = an / bn;
928  return static_cast<gnc_numeric>(convert(quot, denom, how));
929  }
930  GncRational ar(a), br(b);
931  auto quot = ar / br;
932  if (denom == GNC_DENOM_AUTO &&
934  return static_cast<gnc_numeric>(quot.round_to_numeric());
935  quot = static_cast<gnc_numeric>(convert(quot, denom, how));
936  if (quot.is_big() || !quot.valid())
938  return static_cast<gnc_numeric>(quot);
939  }
940  catch (const std::overflow_error& err)
941  {
942  PWARN("%s", err.what());
944  }
945  catch (const std::invalid_argument& err)
946  {
947  PWARN("%s", err.what());
949  }
950  catch (const std::underflow_error& err) //Divide by zero
951  {
952  PWARN("%s", err.what());
954  }
955  catch (const std::domain_error& err)
956  {
957  PWARN("%s", err.what());
959  }
960 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:233
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:189
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:226
#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:225
Rational number class using GncInt128 for the numerator and denominator.
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:178
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:246
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:127

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

698 {
699  if (gnc_numeric_check(a))
700  {
701  /* a is not a valid number, check b */
702  if (gnc_numeric_check(b))
703  /* Both invalid, consider them equal */
704  return TRUE;
705  else
706  /* a invalid, b valid */
707  return FALSE;
708  }
709  if (gnc_numeric_check(b))
710  /* a valid, b invalid */
711  return FALSE;
712 
713  return gnc_numeric_compare (a, b) == 0;
714 }
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_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 1100 of file gnc-numeric.cpp.

1101 {
1102  if (num.num == 0)
1103  return gnc_numeric_zero();
1104  try
1105  {
1106  return static_cast<gnc_numeric>(GncNumeric(num).inv());
1107  }
1108  catch (const std::overflow_error& err)
1109  {
1110  PWARN("%s", err.what());
1112  }
1113  catch (const std::invalid_argument& err)
1114  {
1115  PWARN("%s", err.what());
1117  }
1118  catch (const std::underflow_error& err)
1119  {
1120  PWARN("%s", err.what());
1122  }
1123  catch (const std::domain_error& err)
1124  {
1125  PWARN("%s", err.what());
1127  }
1128 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:233
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:226
#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:225
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 859 of file gnc-numeric.cpp.

861 {
863  {
865  }
866 
867  try
868  {
869  denom = denom_lcd(a, b, denom, how);
870  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
871  {
872  GncNumeric an (a), bn (b);
873  auto prod = an * bn;
874  return static_cast<gnc_numeric>(convert(prod, denom, how));
875  }
876  GncRational ar(a), br(b);
877  auto prod = ar * br;
878  if (denom == GNC_DENOM_AUTO &&
880  return static_cast<gnc_numeric>(prod.round_to_numeric());
881  prod = convert(prod, denom, how);
882  if (prod.is_big() || !prod.valid())
884  return static_cast<gnc_numeric>(prod);
885  }
886  catch (const std::overflow_error& err)
887  {
888  PWARN("%s", err.what());
890  }
891  catch (const std::invalid_argument& err)
892  {
893  PWARN("%s", err.what());
895  }
896  catch (const std::underflow_error& err)
897  {
898  PWARN("%s", err.what());
900  }
901  catch (const std::domain_error& err)
902  {
903  PWARN("%s", err.what());
905  }
906 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:233
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:189
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:226
#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:225
Rational number class using GncInt128 for the numerator and denominator.
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:178
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:246
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:127

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

969 {
970  if (gnc_numeric_check(a))
971  {
973  }
974  return gnc_numeric_create(- a.num, a.denom);
975 }
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:225
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 609 of file gnc-numeric.cpp.

610 {
611  if (gnc_numeric_check(a))
612  {
613  return 0;
614  }
615  else
616  {
617  if ((a.num < 0) && (a.denom != 0))
618  {
619  return 1;
620  }
621  else
622  {
623  return 0;
624  }
625  }
626 }
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 633 of file gnc-numeric.cpp.

634 {
635  if (gnc_numeric_check(a))
636  {
637  return 0;
638  }
639  else
640  {
641  if ((a.num > 0) && (a.denom != 0))
642  {
643  return 1;
644  }
645  else
646  {
647  return 0;
648  }
649  }
650 }
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 724 of file gnc-numeric.cpp.

726 {
727  gnc_numeric aconv, bconv;
728 
729  aconv = gnc_numeric_convert(a, denom, how);
730  bconv = gnc_numeric_convert(b, denom, how);
731 
732  return(gnc_numeric_equal(aconv, bconv));
733 }
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 805 of file gnc-numeric.cpp.

807 {
808  gnc_numeric nb;
810  {
812  }
813  try
814  {
815  denom = denom_lcd(a, b, denom, how);
816  if ((how & GNC_NUMERIC_DENOM_MASK) != GNC_HOW_DENOM_EXACT)
817  {
818  GncNumeric an (a), bn (b);
819  auto sum = an - bn;
820  return static_cast<gnc_numeric>(convert(sum, denom, how));
821  }
822  GncRational ar(a), br(b);
823  auto sum = ar - br;
824  if (denom == GNC_DENOM_AUTO &&
826  return static_cast<gnc_numeric>(sum.round_to_numeric());
827  sum = convert(sum, denom, how);
828  if (sum.is_big() || !sum.valid())
830  return static_cast<gnc_numeric>(sum);
831  }
832  catch (const std::overflow_error& err)
833  {
834  PWARN("%s", err.what());
836  }
837  catch (const std::invalid_argument& err)
838  {
839  PWARN("%s", err.what());
841  }
842  catch (const std::underflow_error& err)
843  {
844  PWARN("%s", err.what());
846  }
847  catch (const std::domain_error& err)
848  {
849  PWARN("%s", err.what());
851  }
852 }
GNC_HOW_RND_NEVER was specified, but the result could not be converted to the desired denominator wit...
Definition: gnc-numeric.h:233
Use any denominator which gives an exactly correct ratio of numerator to denominator.
Definition: gnc-numeric.h:189
The primary numeric class for representing amounts and values.
Definition: gnc-numeric.hpp:59
Intermediate result overflow.
Definition: gnc-numeric.h:226
#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:225
Rational number class using GncInt128 for the numerator and denominator.
Never round at all, and signal an error if there is a fractional result in a computation.
Definition: gnc-numeric.h:178
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:246
#define GNC_NUMERIC_RND_MASK
bitmasks for HOW flags.
Definition: gnc-numeric.h:127

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

1080 {
1081  int max_places = max_decimal_places == NULL ? max_leg_digits :
1082  *max_decimal_places;
1083  if (a->num == 0) return TRUE;
1084  try
1085  {
1086  GncNumeric an (*a);
1087  auto bn = an.to_decimal(max_places);
1088  *a = static_cast<gnc_numeric>(bn);
1089  return TRUE;
1090  }
1091  catch (const std::exception& err)
1092  {
1093  PWARN("%s", err.what());
1094  return FALSE;
1095  }
1096 }
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_to_double()

gdouble gnc_numeric_to_double ( gnc_numeric  n)

Convert numeric to floating-point value.

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

1173 {
1174  if (in.denom > 0)
1175  {
1176  return (double)in.num / (double)in.denom;
1177  }
1178  else
1179  {
1180  return (double)(in.num * -in.denom);
1181  }
1182 }

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

1202 {
1203  gchar *result;
1204  gint64 tmpnum = n.num;
1205  gint64 tmpdenom = n.denom;
1206 
1207  result = g_strdup_printf("%" G_GINT64_FORMAT "/%" G_GINT64_FORMAT, tmpnum, tmpdenom);
1208 
1209  return result;
1210 }

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

586 {
587  if (gnc_numeric_check(a))
588  {
589  return 0;
590  }
591  else
592  {
593  if ((a.num == 0) && (a.denom != 0))
594  {
595  return 1;
596  }
597  else
598  {
599  return 0;
600  }
601  }
602 }
GNCNumericErrorCode gnc_numeric_check(gnc_numeric in)
Check for error signal in value.

◆ string_to_gnc_numeric()

gboolean string_to_gnc_numeric ( const gchar *  str,
gnc_numeric *  n 
)

Read a gnc_numeric from str, skipping any leading whitespace.

Return TRUE on success and store the resulting value in "n". Return NULL on error.

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

1230 {
1231  try
1232  {
1233  GncNumeric an(str);
1234  *n = static_cast<gnc_numeric>(an);
1235  return TRUE;
1236  }
1237  catch (const std::exception& err)
1238  {
1239  PWARN("%s", err.what());
1240  return FALSE;
1241  }
1242 }
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