diff options
author | Florian Dold <florian.dold@gmail.com> | 2020-01-17 18:59:15 +0100 |
---|---|---|
committer | Florian Dold <florian.dold@gmail.com> | 2020-01-17 18:59:15 +0100 |
commit | 7378b5a081a0d839c3bd63f6ddd359bca50be695 (patch) | |
tree | ce62b33d65e6372ea59ae7409b193824735ac538 /src/util | |
parent | ac2e40d0491c0f118ff26cb316ec47e0786818e7 (diff) |
amount rounding a la Christian
Diffstat (limited to 'src/util')
-rw-r--r-- | src/util/amount.c | 16 | ||||
-rw-r--r-- | src/util/test_amount.c | 15 |
2 files changed, 22 insertions, 9 deletions
diff --git a/src/util/amount.c b/src/util/amount.c index 48f5d9891..1f00b1d6e 100644 --- a/src/util/amount.c +++ b/src/util/amount.c @@ -674,23 +674,27 @@ TALER_amount_divide (struct TALER_Amount *result, /** * Round the amount to something that can be transferred on the wire. + * The rounding mode is specified via the smallest transferable unit, + * which must only have a fractional part. * * @param[in,out] amount amount to round down - * @param max_fractional_digits number of fractional digits to round down to + * @param[in] round_unit unit that should be rounded down to, + * the value part of this amount must be zero * @return #GNUNET_OK on success, #GNUNET_NO if rounding was unnecessary, * #GNUNET_SYSERR if the amount or currency was invalid */ int TALER_amount_round_down (struct TALER_Amount *amount, - uint8_t max_fractional_digits) + const struct TALER_Amount *round_unit) { uint32_t delta; - uint32_t divisor = 1; - for (unsigned int i = 0; i < max_fractional_digits; i++) - divisor *= 10; + GNUNET_break (0 == round_unit->value); - delta = amount->fraction % (TALER_AMOUNT_FRAC_BASE / divisor); + if (0 == round_unit->fraction) + return GNUNET_OK; + + delta = amount->fraction % round_unit->fraction; if (0 == delta) return GNUNET_NO; amount->fraction -= delta; diff --git a/src/util/test_amount.c b/src/util/test_amount.c index 4eeccd7e0..3bf8e6fb0 100644 --- a/src/util/test_amount.c +++ b/src/util/test_amount.c @@ -31,6 +31,7 @@ main (int argc, struct TALER_Amount a1; struct TALER_Amount a2; struct TALER_Amount a3; + struct TALER_Amount r; char *c; GNUNET_log_setup ("test-amout", @@ -237,25 +238,33 @@ main (int argc, /* test rounding #1 */ GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:0.01", + &r)); + + GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:4.001", &a1)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:4", &a2)); - GNUNET_assert (GNUNET_OK == TALER_amount_round_down (&a1, 2)); - GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, 2)); + GNUNET_assert (GNUNET_OK == TALER_amount_round_down (&a1, &r)); + GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, &r)); GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2)); /* test rounding #2 */ GNUNET_assert (GNUNET_OK == + TALER_string_to_amount ("EUR:0.001", + &r)); + + GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:4.001", &a1)); GNUNET_assert (GNUNET_OK == TALER_string_to_amount ("EUR:4.001", &a2)); - GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, 3)); + GNUNET_assert (GNUNET_NO == TALER_amount_round_down (&a1, &r)); GNUNET_assert (0 == TALER_amount_cmp (&a1, &a2)); return 0; |