Abstracted precision extension constant, and added a note that precision must
be handled differently, since paying attention to places after the decimal is not enough.
This commit is contained in:
parent
7ce1c4e5a9
commit
c172281858
2 changed files with 23 additions and 8 deletions
|
|
@ -494,9 +494,10 @@ amount_t& amount_t::operator*=(const amount_t& amt)
|
||||||
|
|
||||||
if (has_commodity() && ! (quantity->has_flags(BIGINT_KEEP_PREC))) {
|
if (has_commodity() && ! (quantity->has_flags(BIGINT_KEEP_PREC))) {
|
||||||
precision_t comm_prec = commodity().precision();
|
precision_t comm_prec = commodity().precision();
|
||||||
if (quantity->prec > comm_prec + 6U) {
|
if (quantity->prec > comm_prec + extend_by_digits) {
|
||||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
|
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec,
|
||||||
quantity->prec = comm_prec + 6U;
|
comm_prec + extend_by_digits);
|
||||||
|
quantity->prec = comm_prec + extend_by_digits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -524,10 +525,17 @@ amount_t& amount_t::operator/=(const amount_t& amt)
|
||||||
// Increase the value's precision, to capture fractional parts after
|
// Increase the value's precision, to capture fractional parts after
|
||||||
// the divide. Round up in the last position.
|
// the divide. Round up in the last position.
|
||||||
|
|
||||||
mpz_ui_pow_ui(divisor, 10, (2 * amt.quantity->prec) + quantity->prec + 7U);
|
// jww (2008-11-13): I need to consider the magnitude of the numerator
|
||||||
|
// of both numbers. For example, if I divide 10 by
|
||||||
|
// 100000000000000000000000000000000000, the result will be 0 because
|
||||||
|
// even extend_by_digits * 2 will not be enough digits of precision to
|
||||||
|
// retain the significance of the answer.
|
||||||
|
|
||||||
|
mpz_ui_pow_ui(divisor, 10,
|
||||||
|
(2 * amt.quantity->prec) + quantity->prec + extend_by_digits + 1U);
|
||||||
mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
|
mpz_mul(MPZ(quantity), MPZ(quantity), divisor);
|
||||||
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
mpz_tdiv_q(MPZ(quantity), MPZ(quantity), MPZ(amt.quantity));
|
||||||
quantity->prec += amt.quantity->prec + quantity->prec + 7U;
|
quantity->prec += amt.quantity->prec + quantity->prec + extend_by_digits + 1U;
|
||||||
|
|
||||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, quantity->prec - 1);
|
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, quantity->prec - 1);
|
||||||
quantity->prec -= 1;
|
quantity->prec -= 1;
|
||||||
|
|
@ -542,9 +550,10 @@ amount_t& amount_t::operator/=(const amount_t& amt)
|
||||||
|
|
||||||
if (has_commodity() && ! (quantity->has_flags(BIGINT_KEEP_PREC))) {
|
if (has_commodity() && ! (quantity->has_flags(BIGINT_KEEP_PREC))) {
|
||||||
precision_t comm_prec = commodity().precision();
|
precision_t comm_prec = commodity().precision();
|
||||||
if (quantity->prec > comm_prec + 6U) {
|
if (quantity->prec > comm_prec + extend_by_digits) {
|
||||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
|
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec,
|
||||||
quantity->prec = comm_prec + 6U;
|
comm_prec + extend_by_digits);
|
||||||
|
quantity->prec = comm_prec + extend_by_digits;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -100,6 +100,12 @@ public:
|
||||||
*/
|
*/
|
||||||
typedef uint_least16_t precision_t;
|
typedef uint_least16_t precision_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The number of places of precision by which values are extended to
|
||||||
|
* avoid losing precision during division and multiplication.
|
||||||
|
*/
|
||||||
|
static const unsigned int extend_by_digits = 8U;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current_pool is a static variable indicating which commodity
|
* The current_pool is a static variable indicating which commodity
|
||||||
* pool should be used.
|
* pool should be used.
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue