I'm trying to build a generic formatting function that takes two integers T
as nominator and denominator, and formats the fraction according to some simple rules.
I had a look at the num
traits, however, still can't make it work. I'm already with much more verbose code than I wanted to so I thought it's time to ask for help.
extern crate num;
use num::{Integer,FromPrimitive};
fn format_rational<T>(n: T, d: T) -> String
where T: Integer + FromPrimitive + fmt::Display
{
let one: T = FromPrimitive::from_u16(1).unwrap();
let ten: T = FromPrimitive::from_u16(10).unwrap();
let hun: T = FromPrimitive::from_u16(100).unwrap();
let tho: T = FromPrimitive::from_u16(1000).unwrap();
let precision = match d {
one => Some(1),
hun => Some(2),
tho => Some(3),
_ => None,
};
match precision {
Some(p) => format!("{:.*}", p, n as f32 / d as f32),
None => format!("{} / {}", n, d),
}
}
This errors with
non-primitive cast: `T` as `f32`
But when I change the first format!
line to
Some(p) => format!("{:.*}", p, f32::from(n) / f32::from(d))
I get this error:
the trait bound `f32: std::convert::From<T>` is not satisfied
which I interpret as "From does not exist for type f32", which makes sense. How is f32
possible here when the trait is Num
, which implies Eq
, which implies it should exclude floats? (as floats only implement PartialEq
). Finally, is there a way to simply work with From<T>
?
What am I missing? Or can the problem be solved in another (easier) way? Thanks!
I solved it today. Are there better ways of doing this?
extern crate num;
use std::fmt;
use num::{ToPrimitive};
pub fn format_rational<T>(n: T, d: T) -> String
where T: ToPrimitive + fmt::Display
{
let precision = match d.to_usize().unwrap() {
1 | 10 => Some(1),
100 => Some(2),
1000 => Some(3),
_ => None,
};
match precision {
Some(p) => format!("{:.*}", p, ToPrimitive::to_f32(&n).unwrap() / ToPrimitive::to_f32(&d).unwrap()),
None => format!("{} / {}", n, d),
}
}
Avoiding some unwrap
s, compared to your answer:
extern crate num;
use std::fmt;
use num::{ToPrimitive};
pub fn format_rational<T>(n: T, d: T) -> String
where
T: ToPrimitive + std::ops::Div + fmt::Display,
<T as std::ops::Div>::Output: fmt::Display,
{
let precision = match d.to_usize() {
Some(1) | Some(10) => Some(1),
Some(100) => Some(2),
Some(1000) => Some(3),
_ => None,
};
match precision {
Some(p) => format!("{:.*}", p, n.div(d)),
None => format!("{} / {}", n, d),
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.