Round `Amount` when requested precision is too low
Low precision was previously not considered because it was believed it could lead to misleading data being displayed. However it's quite possible that people using low precision know what they are doing and it's sometimes useful to show rounded numbers. To enable low precision we just compute what the rounded number would be and display that one instead. This actually fully closes #2136 since this issue was mentioned there along with previously-fixed displaying of higher precisions.
This commit is contained in:
parent
7c95a777c1
commit
467546fc0c
|
@ -711,7 +711,7 @@ fn repeat_char(f: &mut dyn fmt::Write, c: char, count: usize) -> fmt::Result {
|
||||||
|
|
||||||
/// Format the given satoshi amount in the given denomination.
|
/// Format the given satoshi amount in the given denomination.
|
||||||
fn fmt_satoshi_in(
|
fn fmt_satoshi_in(
|
||||||
satoshi: u64,
|
mut satoshi: u64,
|
||||||
negative: bool,
|
negative: bool,
|
||||||
f: &mut dyn fmt::Write,
|
f: &mut dyn fmt::Write,
|
||||||
denom: Denomination,
|
denom: Denomination,
|
||||||
|
@ -736,6 +736,19 @@ fn fmt_satoshi_in(
|
||||||
}
|
}
|
||||||
Ordering::Less => {
|
Ordering::Less => {
|
||||||
let precision = precision.unsigned_abs();
|
let precision = precision.unsigned_abs();
|
||||||
|
// round the number if needed
|
||||||
|
// rather than fiddling with chars, we just modify satoshi and let the simpler algorithm take over.
|
||||||
|
if let Some(format_precision) = options.precision {
|
||||||
|
if usize::from(precision) > format_precision {
|
||||||
|
// precision is u8 so in this branch options.precision() < 255 which fits in u32
|
||||||
|
let rounding_divisor = 10u64.pow(u32::from(precision) - format_precision as u32);
|
||||||
|
let remainder = satoshi % rounding_divisor;
|
||||||
|
satoshi -= remainder;
|
||||||
|
if remainder / (rounding_divisor / 10) >= 5 {
|
||||||
|
satoshi += rounding_divisor;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
let divisor = 10u64.pow(precision.into());
|
let divisor = 10u64.pow(precision.into());
|
||||||
num_before_decimal_point = satoshi / divisor;
|
num_before_decimal_point = satoshi / divisor;
|
||||||
num_after_decimal_point = satoshi % divisor;
|
num_after_decimal_point = satoshi % divisor;
|
||||||
|
@ -2391,10 +2404,10 @@ mod tests {
|
||||||
btc_check_fmt_non_negative_6, 1, "{}", "0.00000001";
|
btc_check_fmt_non_negative_6, 1, "{}", "0.00000001";
|
||||||
btc_check_fmt_non_negative_7, 1, "{:2}", "0.00000001";
|
btc_check_fmt_non_negative_7, 1, "{:2}", "0.00000001";
|
||||||
btc_check_fmt_non_negative_8, 1, "{:02}", "0.00000001";
|
btc_check_fmt_non_negative_8, 1, "{:02}", "0.00000001";
|
||||||
btc_check_fmt_non_negative_9, 1, "{:.1}", "0.00000001";
|
btc_check_fmt_non_negative_9, 1, "{:.1}", "0.0";
|
||||||
btc_check_fmt_non_negative_10, 1, "{:11}", " 0.00000001";
|
btc_check_fmt_non_negative_10, 1, "{:11}", " 0.00000001";
|
||||||
btc_check_fmt_non_negative_11, 1, "{:11.1}", " 0.00000001";
|
btc_check_fmt_non_negative_11, 1, "{:11.1}", " 0.0";
|
||||||
btc_check_fmt_non_negative_12, 1, "{:011.1}", "00.00000001";
|
btc_check_fmt_non_negative_12, 1, "{:011.1}", "000000000.0";
|
||||||
btc_check_fmt_non_negative_13, 1, "{:.9}", "0.000000010";
|
btc_check_fmt_non_negative_13, 1, "{:.9}", "0.000000010";
|
||||||
btc_check_fmt_non_negative_14, 1, "{:11.9}", "0.000000010";
|
btc_check_fmt_non_negative_14, 1, "{:11.9}", "0.000000010";
|
||||||
btc_check_fmt_non_negative_15, 1, "{:011.9}", "0.000000010";
|
btc_check_fmt_non_negative_15, 1, "{:011.9}", "0.000000010";
|
||||||
|
@ -2409,7 +2422,7 @@ mod tests {
|
||||||
btc_check_fmt_non_negative_24, 110_000_000, "{}", "1.1";
|
btc_check_fmt_non_negative_24, 110_000_000, "{}", "1.1";
|
||||||
btc_check_fmt_non_negative_25, 100_000_001, "{}", "1.00000001";
|
btc_check_fmt_non_negative_25, 100_000_001, "{}", "1.00000001";
|
||||||
btc_check_fmt_non_negative_26, 100_000_001, "{:1}", "1.00000001";
|
btc_check_fmt_non_negative_26, 100_000_001, "{:1}", "1.00000001";
|
||||||
btc_check_fmt_non_negative_27, 100_000_001, "{:.1}", "1.00000001";
|
btc_check_fmt_non_negative_27, 100_000_001, "{:.1}", "1.0";
|
||||||
btc_check_fmt_non_negative_28, 100_000_001, "{:10}", "1.00000001";
|
btc_check_fmt_non_negative_28, 100_000_001, "{:10}", "1.00000001";
|
||||||
btc_check_fmt_non_negative_29, 100_000_001, "{:11}", " 1.00000001";
|
btc_check_fmt_non_negative_29, 100_000_001, "{:11}", " 1.00000001";
|
||||||
btc_check_fmt_non_negative_30, 100_000_001, "{:011}", "01.00000001";
|
btc_check_fmt_non_negative_30, 100_000_001, "{:011}", "01.00000001";
|
||||||
|
@ -2441,7 +2454,7 @@ mod tests {
|
||||||
|
|
||||||
check_format_non_negative_show_denom! {
|
check_format_non_negative_show_denom! {
|
||||||
Bitcoin, " BTC";
|
Bitcoin, " BTC";
|
||||||
btc_check_fmt_non_negative_show_denom_0, 1, "{:14.1}", "0.00000001";
|
btc_check_fmt_non_negative_show_denom_0, 1, "{:14.1}", " 0.0";
|
||||||
btc_check_fmt_non_negative_show_denom_1, 1, "{:14.8}", "0.00000001";
|
btc_check_fmt_non_negative_show_denom_1, 1, "{:14.8}", "0.00000001";
|
||||||
btc_check_fmt_non_negative_show_denom_2, 1, "{:15}", " 0.00000001";
|
btc_check_fmt_non_negative_show_denom_2, 1, "{:15}", " 0.00000001";
|
||||||
btc_check_fmt_non_negative_show_denom_3, 1, "{:015}", "00.00000001";
|
btc_check_fmt_non_negative_show_denom_3, 1, "{:015}", "00.00000001";
|
||||||
|
@ -2872,14 +2885,17 @@ mod tests {
|
||||||
assert_eq!(format!("{}", Amount::ONE_BTC), "1 BTC");
|
assert_eq!(format!("{}", Amount::ONE_BTC), "1 BTC");
|
||||||
assert_eq!(format!("{}", Amount::from_sat(1)), "0.00000001 BTC");
|
assert_eq!(format!("{}", Amount::from_sat(1)), "0.00000001 BTC");
|
||||||
assert_eq!(format!("{}", Amount::from_sat(10)), "0.0000001 BTC");
|
assert_eq!(format!("{}", Amount::from_sat(10)), "0.0000001 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(10)), "0.0000001 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(10)), "0.00 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(100)), "0.000001 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(100)), "0.00 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(1000)), "0.00001 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(1000)), "0.00 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(10_000)), "0.0001 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(10_000)), "0.00 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(100_000)), "0.001 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(100_000)), "0.00 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(1_000_000)), "0.01 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(1_000_000)), "0.01 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(10_000_000)), "0.10 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(10_000_000)), "0.10 BTC");
|
||||||
assert_eq!(format!("{:.2}", Amount::from_sat(100_000_000)), "1.00 BTC");
|
assert_eq!(format!("{:.2}", Amount::from_sat(100_000_000)), "1.00 BTC");
|
||||||
|
assert_eq!(format!("{:.2}", Amount::from_sat(500_000)), "0.01 BTC");
|
||||||
|
assert_eq!(format!("{:.2}", Amount::from_sat(9_500_000)), "0.10 BTC");
|
||||||
|
assert_eq!(format!("{:.2}", Amount::from_sat(99_500_000)), "1.00 BTC");
|
||||||
assert_eq!(format!("{}", Amount::from_sat(100_000_000)), "1 BTC");
|
assert_eq!(format!("{}", Amount::from_sat(100_000_000)), "1 BTC");
|
||||||
assert_eq!(format!("{}", Amount::from_sat(40_000_000_000)), "400 BTC");
|
assert_eq!(format!("{}", Amount::from_sat(40_000_000_000)), "400 BTC");
|
||||||
assert_eq!(format!("{:.10}", Amount::from_sat(100_000_000)), "1.0000000000 BTC");
|
assert_eq!(format!("{:.10}", Amount::from_sat(100_000_000)), "1.0000000000 BTC");
|
||||||
|
|
Loading…
Reference in New Issue