Skip to content

Instantly share code, notes, and snippets.

@trentj

trentj/main.rs Secret

Created October 24, 2020 15:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save trentj/e28aa0a58156869d443fc11cfc938cd4 to your computer and use it in GitHub Desktop.
Save trentj/e28aa0a58156869d443fc11cfc938cd4 to your computer and use it in GitHub Desktop.
Precision conversions using integers vs. floats
fn convert_precision_f(amount: i64, from: u64, to: u64) -> Option<i64> {
let mut new_amount = amount as f64;
let precision_diff = to as f64 - from as f64;
// If the precision as increased
if precision_diff > 0.0 {
new_amount = new_amount * 10.0_f64.powf(precision_diff);
} else if precision_diff < 0.0 {
new_amount = new_amount / 10.0_f64.powf(precision_diff.abs());
}
round(new_amount)
}
fn round(value: f64) -> Option<i64> {
// don't trust the rounding system of the compiler.
// truncate all the decimals.
let mut num_int: i64 = value.trunc() as i64;
// calculate the decimals by the difference between
// the truncated integer and the given value
let num_dec = (value - (num_int as f64)).abs();
if num_dec == 0.5 {
// if the number is not even and is positive
if num_int % 2 != 0 && num_int > 0 {
// add one
num_int += 1;
}
// if the number is not even and is negative
else if num_int % 2 != 0 && num_int < 0 {
// subtract one: this is the symmetry between positive and
// negative numbers
num_int -= 1;
}
}
// round as normal:
// - greater than 0.5: adds one
// - lesser than 0.5: don't add
else if num_dec > 0.5 && num_int > 0 {
num_int = num_int.checked_add(1)?;
}
Some(num_int)
}
fn convert_precision_i(amount: i64, from: u64, to: u64) -> Option<i64> {
let mut amount = amount;
if from > to {
let mut round_up = false;
for _ in 0..(from - to) {
round_up = amount % 10 > 5;
amount /= 10;
}
Some(amount + round_up as i64)
} else {
for _ in 0..(to - from) {
amount = amount.checked_mul(10)?;
}
Some(amount)
}
}
fn main() {
use rand::Rng;
let mut rng = rand::thread_rng();
let (from, to) = (0, 2);
loop {
let x = rng.gen();
let f = convert_precision_f(x, from, to);
let i = convert_precision_i(x, from, to);
if f != i {
eprintln!("{:20} ({:?} != {:?})", x, f, i);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment