akubera / bigdecimal-rs

Arbitrary precision decimal crate for Rust
Other
283 stars 71 forks source link

Override to_i128 and to_u128 in BigDecimal #89

Closed 24seconds closed 1 year ago

24seconds commented 2 years ago

Description

Hello, I got a question about converting logic of BigDecimal in the repo which I worked on. Currently the repo I worked on is highly using this repo :smile: Thanks always.

I saw the bigdecimal-rs implementation about ToPrimitive trait. BigDecimal struct implements three functions, to_i64, to_u64 and to_f64.

Problem

The problem is when we need to handle the i128 or u128 type. Currently BigDecimal can not handle the i128 range number, for example 170141183460469231731687303715884105727 - the max number of i128. Therefore, test case below will be failed now.

fn test_to_i128() {
    let vals = vec![
        ("170141183460469231731687303715884105727", 170141183460469231731687303715884105727),
        ("-170141183460469231731687303715884105728", -170141183460469231731687303715884105728),
        ("12.34", 12),
        ("3.14", 3),
        ("50", 50),            
        ("0.001", 0),
    ];
    for (s, ans) in vals {
        let calculated = BigDecimal::from_str(s).unwrap().to_i128().unwrap();

        assert_eq!(ans, calculated);
    }
}

ToPrimitive trait

This is because the ToPrimitive's implementation.
ToPrimitive trait is residing in the num-traits repo. In that repo the description about to_i128 explains why.

/// Converts the value of self to an i128. If the value cannot be /// represented by an i128 (i64 under the default implementation), then /// None is returned. /// /// The default implementation converts through to_i64(). Types implementing /// this trait should override this method if they can represent a greater range.

quote link

Suggestion

Therefore, I suggest to override to_i128 and to_u128 in BigDecimal struct for the better handling the big number. I added two test cases for the check.