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))) {
|
||||
precision_t comm_prec = commodity().precision();
|
||||
if (quantity->prec > comm_prec + 6U) {
|
||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
|
||||
quantity->prec = comm_prec + 6U;
|
||||
if (quantity->prec > comm_prec + extend_by_digits) {
|
||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec,
|
||||
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
|
||||
// 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_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);
|
||||
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))) {
|
||||
precision_t comm_prec = commodity().precision();
|
||||
if (quantity->prec > comm_prec + 6U) {
|
||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec, comm_prec + 6U);
|
||||
quantity->prec = comm_prec + 6U;
|
||||
if (quantity->prec > comm_prec + extend_by_digits) {
|
||||
mpz_round(MPZ(quantity), MPZ(quantity), quantity->prec,
|
||||
comm_prec + extend_by_digits);
|
||||
quantity->prec = comm_prec + extend_by_digits;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -100,6 +100,12 @@ public:
|
|||
*/
|
||||
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
|
||||
* pool should be used.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue