Created
January 9, 2024 14:57
-
-
Save unfo/c504ee31dc2311cae6bdb973d4f5345c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
[package] | |
name = "minimum_sample_size" | |
version = "0.1.0" | |
edition = "2021" | |
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html | |
[dependencies] | |
clap = { version = "4.4.14", features = ["derive"] } | |
num-integer = "0.1.45" |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
use clap::Parser; | |
use num_integer::Integer; | |
#[derive(Parser, Debug)] | |
#[command(author, version, about, long_about = None)] | |
struct Args { | |
// target precision we're after | |
#[arg(default_value_t = 1.0f64)] | |
target: f64, | |
#[arg(default_value_t = 0u32)] | |
repeating_decimals: u32 | |
} | |
fn main() { | |
let args = Args::parse(); | |
let precision: f64 = args.target; | |
let repeating: u32 = args.repeating_decimals; | |
match calculate_minimum_sample_size(precision, repeating) { | |
Some(size) => println!("Minimum number of people required: {}", size), | |
None => println!("Precision too fine to calculate with this method"), | |
} | |
} | |
fn calculate_minimum_sample_size(precision: f64, repeating_decimals: u32) -> Option<usize> { | |
if precision <= 0.0 || precision >= 1.0 { | |
return None; | |
} | |
let decimal_places = count_decimal_places(precision); | |
if repeating_decimals > 0 { | |
let power = repeating_decimals; | |
let denominator = 10usize.pow(power) - 1; | |
let multiplied = precision * 10f64.powi(power as i32); | |
let repeating_part = multiplied - multiplied.floor(); | |
let mut repetition_added = multiplied; | |
for n in 0..repeating_decimals { | |
let f = (n + 1) as f64; | |
repetition_added += repeating_part * 10f64.powf(f * -1.0); | |
} | |
let subbed = repetition_added - precision; | |
let subbed_decimal = count_decimal_places(subbed); | |
let final_num = (subbed * 10f64.powi(subbed_decimal as i32)) as usize; | |
let final_den = denominator * 10usize.pow(subbed_decimal); | |
let gcd: usize = final_num.gcd(&final_den); | |
Some(final_den / gcd) | |
} else { | |
let power = decimal_places; | |
let denominator = 10usize.pow(power); | |
let multiplied = (precision * 10f64.powi(power as i32)) as usize; | |
let gcd = multiplied.gcd(&denominator); | |
Some(denominator / gcd) | |
} | |
} | |
fn count_decimal_places(input: f64) -> u32 { | |
let input_str = input.to_string(); | |
let parts: Vec<&str> = input_str.split('.').collect(); | |
if parts.len() == 2 { | |
parts[1].trim_end_matches('0').len() as u32 | |
} else { | |
0 | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment