assert_be_close/lib.rs
1use std::fmt::Display;
2
3use num::Float;
4
5/// Asserts that two decimals are equal with the specified precision.
6/// On panic, the function will print the value of the decimal with their debug representations.
7/// 2つの小数が指定した精度で等しいことを保証する。
8/// パニックになると、この関数は小数の値をデバッグ表現とともに出力する。
9///
10/// # Panics
11///
12/// Panic if the value is not equivalent to the specified precision.
13/// 値が指定した精度で等価でなければパニックする。
14///
15/// # Examples
16///
17/// ```should_panic
18/// use assert_be_close::assert_be_close;
19///
20/// assert_be_close(1.0, 1.0001, 3);
21/// assert_be_close(1.0, 1.0001, 4); // panic
22/// ```
23pub fn assert_be_close<T: Float + Display>(left: T, right: T, precision: i32) {
24 let expected_diff = T::from(10.0).unwrap().powi(-precision) / T::from(2.0).unwrap();
25 let received_diff = (left - right).abs();
26
27 if received_diff >= expected_diff {
28 panic!("assertion 'left ≈ right` failed\n left: {}\nright: {}\nreceived_diff: {}\nexpected_diff: {}", left, right, received_diff, expected_diff);
29 }
30}
31
32/// Asserts that two decimals aren't equal with the specified precision.
33/// On panic, the function will print the value of the decimal with their debug representations.
34/// 2つの小数が指定した精度で等しくないことを保証する。
35/// パニックになると、この関数は小数の値をデバッグ表現とともに出力する。
36///
37/// # Panics
38///
39/// Panic if the value is equivalent to the specified precision.
40/// 値が指定した精度で等価であるとパニックする。
41///
42/// # Examples
43///
44/// ```should_panic
45/// use assert_be_close::assert_not_close;
46///
47/// assert_not_close(1.0, 1.0001, 4);
48/// assert_not_close(1.0, 1.0001, 3); // panic
49/// ```
50pub fn assert_not_close<T: Float + Display>(left: T, right: T, precision: i32) {
51 let expected_diff = T::from(10.0).unwrap().powi(-precision) / T::from(2.0).unwrap();
52 let received_diff = (left - right).abs();
53
54 if received_diff <= expected_diff {
55 panic!("assertion 'left != right` failed\n left: {}\nright: {}\nreceived_diff: {}\nexpected_diff: {}", left, right, received_diff, expected_diff);
56 }
57}
58
59
60#[cfg(test)]
61mod test {
62 use super::*;
63
64 #[test]
65 fn assert_be_close_works() {
66 assert_be_close(1.0, 1.0001, 3);
67 }
68
69 #[test]
70 fn assert_not_close_works() {
71 assert_not_close(1.0, 1.0001, 4);
72 }
73}