use bigdecimal::BigDecimal;
use num_bigint::BigInt;
use num_traits::{FromPrimitive, Pow};
use rand::{thread_rng, Rng};
use tracing::error;
pub trait RandomNumber<T> {
fn random(low: T, high: T) -> T;
}
impl RandomNumber<i8> for i8 {
fn random(low: i8, high: i8) -> i8 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<i16> for i16 {
fn random(low: i16, high: i16) -> i16 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<i32> for i32 {
fn random(low: i32, high: i32) -> i32 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<i64> for i64 {
fn random(low: i64, high: i64) -> i64 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<u8> for u8 {
fn random(low: u8, high: u8) -> u8 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<u16> for u16 {
fn random(low: u16, high: u16) -> u16 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<u32> for u32 {
fn random(low: u32, high: u32) -> u32 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<u64> for u64 {
fn random(low: u64, high: u64) -> u64 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<f32> for f32 {
fn random(low: f32, high: f32) -> f32 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<f64> for f64 {
fn random(low: f64, high: f64) -> f64 {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<isize> for isize {
fn random(low: isize, high: isize) -> isize {
thread_rng().gen_range(low..=high)
}
}
impl RandomNumber<usize> for usize {
fn random(low: usize, high: usize) -> usize {
thread_rng().gen_range(low..=high)
}
}
pub trait RoundNumber<Num> {
fn round_num(&self, round_digit: i16, half_up: bool) -> Num;
}
impl RoundNumber<f32> for f32 {
fn round_num(&self, round_digit: i16, half_up: bool) -> f32 {
match BigDecimal::from_f32(*self) {
None => *self,
Some(v) => match half_up {
true => match v.round(round_digit as i64).to_string().parse::<f32>() {
Ok(v) => v,
Err(err) => {
error!("数字转换失败: {}, reason: {:?}", self, err);
*self
}
},
false => {
let multiplier: f64 = 10.0f64.pow(round_digit);
let num = ((*self as f64) * multiplier) as i64;
match BigDecimal::new(BigInt::from(num), round_digit as i64).to_string().parse::<f32>() {
Ok(v) => v,
Err(err) => {
error!("数字转换失败: {}, reason: {:?}", self, err);
*self
}
}
}
},
}
}
}
impl RoundNumber<f64> for f64 {
fn round_num(&self, round_digit: i16, half_up: bool) -> f64 {
match BigDecimal::from_f64(*self) {
None => *self,
Some(v) => match half_up {
true => match v.round(round_digit as i64).to_string().parse::<f64>() {
Ok(v) => v,
Err(err) => {
error!("数字转换失败: {}, reason: {:?}", self, err);
*self
}
},
false => {
let multiplier: f64 = 10.0f64.pow(round_digit);
let num = ((*self) * multiplier) as i64;
match BigDecimal::new(BigInt::from(num), round_digit as i64).to_string().parse::<f64>() {
Ok(v) => v,
Err(err) => {
error!("数字转换失败: {}, reason: {:?}", self, err);
*self
}
}
}
},
}
}
}