Created
September 4, 2024 00:49
-
-
Save nth10sd/5e3e23ec3e823d0ed00c41164f221eb0 to your computer and use it in GitHub Desktop.
Calculations of pi approximations and their accuracies, using cargo-script (still in Rust 1.83.0 nightly as of 20240903)
This file contains 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
### Start | |
# Tested on Linux only, as of 20240903, rustup required, Rust/Cargo at 1.83.0 on nightly | |
# Copy and paste the entire code into the terminal | |
export CARGO_SCRIPT_PATH=/tmp/cargo-script-"$(date -u +%Y%m%d)".rs ; | |
export RUSTUP_DEFAULT="$(rustup default | awk -F "-" '{ print $1 }')" ; | |
if [ ! "$RUSTUP_DEFAULT" = "nightly" ] ; then \ | |
( rustup default nightly 2>&1 ) > /dev/null ; | |
fi ; | |
cat << EOF > "$CARGO_SCRIPT_PATH" | |
---cargo | |
[package] | |
edition = "2021" | |
[dependencies] | |
astro-float = "0.9.4" | |
[profile.dev] | |
codegen-units = 1 | |
debug = false | |
lto = true | |
opt-level = 3 | |
strip = true | |
--- | |
fn main() { | |
use astro_float::{ Consts, RoundingMode, ctx::Context, expr }; | |
let prec = 128 + 8; // 128-bit precision is needed, with a little more for buffer | |
let mut ctx = Context::new( | |
prec, | |
RoundingMode::ToEven, | |
Consts::new().expect("Constants cache initialized"), | |
-100000, // Exponent range from -100000 to 100000 | |
100000 | |
); | |
let actual_pi = ctx.const_pi(); | |
let pi_3pt14 = expr!((2 * 157) / (pow(2, 2) * pow(5, 2)), &mut ctx); | |
println!( | |
"\n3.14 pi, accurate if rounded to 2 decimal places, difference is: {}%", | |
pi_3pt14 | |
.sub_full_prec(&actual_pi) | |
.abs() | |
.mul_full_prec(&expr!(100, &mut ctx)) | |
.div(&actual_pi, prec, RoundingMode::ToEven) | |
); | |
println!("{}", pi_3pt14.to_string()); | |
println!(" 012"); | |
println!(" 012"); | |
let pi_22_7 = expr!(22 / 7, &mut ctx); | |
println!( | |
"\n22/7 pi, accurate if rounded to 2 decimal places, difference is: {}%", | |
pi_22_7 | |
.sub_full_prec(&actual_pi) | |
.abs() | |
.mul_full_prec(&expr!(100, &mut ctx)) | |
.div(&actual_pi, prec, RoundingMode::ToEven) | |
); | |
println!("{}", pi_22_7.to_string()); | |
println!(" 012"); | |
println!(" 012"); | |
let pi_3pt142 = expr!((2 * 1571) / (pow(2, 3) * pow(5, 3)), &mut ctx); | |
println!( | |
"\n3.142 pi, accurate if rounded to 3 decimal places, difference is: {}%", | |
pi_3pt142 | |
.sub_full_prec(&actual_pi) | |
.abs() | |
.mul_full_prec(&expr!(100, &mut ctx)) | |
.div(&actual_pi, prec, RoundingMode::ToEven) | |
); | |
println!("{}", pi_3pt142.to_string()); | |
println!(" 0123"); | |
println!(" 0123"); | |
let pi_355_113 = expr!(355 / 113, &mut ctx); | |
println!( | |
"\n355/113 pi, accurate if rounded to 6 decimal places, difference is: {}%", | |
pi_355_113 | |
.sub_full_prec(&actual_pi) | |
.abs() | |
.mul_full_prec(&expr!(100, &mut ctx)) | |
.div(&actual_pi, prec, RoundingMode::ToEven) | |
); | |
println!("{}", pi_355_113.to_string()); | |
println!(" 0123456"); | |
println!(" 0123456"); | |
let pi_to_16_dp = expr!((2 * 29 * 1009 * 4201) / (3 * 53 * 577 * 853), &mut ctx); | |
println!( | |
concat!( | |
"\n245850922/78256779 pi, accurate if rounded to 16 decimal places,", | |
" difference is: {}%" | |
), | |
pi_to_16_dp | |
.sub_full_prec(&actual_pi) | |
.abs() | |
.mul_full_prec(&expr!(100, &mut ctx)) | |
.div(&actual_pi, prec, RoundingMode::ToEven) | |
); | |
println!("{}", pi_to_16_dp.to_string()); | |
println!(" 01234567890123456"); | |
println!(" 1123456"); | |
let pi_to_37_dp = expr!( | |
(43 * 2515283 * 145232751681480921457117807109) / (pow(2, 36) * pow(5, 37)), | |
&mut ctx | |
); | |
println!( | |
concat!( | |
"\n3.1415926535897932384626433832795028842 pi,", | |
" accurate if rounded to 37 decimal places, difference is: {}%" | |
), | |
pi_to_37_dp | |
.sub_full_prec(&actual_pi) | |
.abs() | |
.mul_full_prec(&expr!(100, &mut ctx)) | |
.div(&actual_pi, prec, RoundingMode::ToEven) | |
); | |
println!("{}", pi_to_37_dp.to_string()); | |
println!(" 01234567890123456789012345678901234567"); | |
println!(" 1 2 31234567"); | |
println!("\nActual pi is:"); | |
println!("{}", actual_pi.to_string()); | |
// Old code not using expr! macro and dealing with BigFloat manually | |
// This calculates pi accurately if rounded to 37 decimal places | |
// let mut cc = Consts::new().expect("Constants cache initialized."); | |
// let rm_none = RoundingMode::None; | |
// let p = 128 + 8; // 128-bit precision is needed, with a little more for buffer | |
// let prime_num_a = BigFloat::parse("11253889508596", Radix::Dec, p, rm_none, | |
// &mut cc); | |
// let prime_num_b = BigFloat::parse("12905116188545173", Radix::Dec, p, rm_none, | |
// &mut cc); | |
// let prime_num_1 = BigFloat::parse("1", Radix::Dec, p, rm_none, &mut cc); | |
// // (43 * 2515283) * ((11253889508596 * 12905116188545173) + 1) | |
// // = 108157169 * 145232751681480921457117807109 | |
// // which is equal to 15707963267948966192313216916397514421 | |
// let numerator = BigFloat::from_word(43 * 2515283, p).mul_full_prec( | |
// &prime_num_a.mul_full_prec(&prime_num_b).add_full_prec(&prime_num_1) | |
// ); | |
// let two_pow_36 = u64::pow(2, 36).to_string(); | |
// let denom_2_pow = BigFloat::parse(&two_pow_36, Radix::Dec, p, rm_none, &mut cc); | |
// let five_pow_19 = u64::pow(5, 19).to_string(); | |
// let denom_5_pow_19 = BigFloat::parse(&five_pow_19, Radix::Dec, p, rm_none, | |
// &mut cc); | |
// let five_pow_18 = u64::pow(5, 18).to_string(); | |
// let denom_5_pow_18 = BigFloat::parse(&five_pow_18, Radix::Dec, p, rm_none, | |
// &mut cc); | |
// // 2**36 * 5**19 * 5**18 = 2**36 * 5**37 | |
// // which is equal to 5000000000000000000000000000000000000 | |
// let denominator = denom_2_pow.mul_full_prec(&denom_5_pow_19).mul_full_prec( | |
// &denom_5_pow_18); | |
// let mut calculated_pi = numerator.div(&denominator, p, rm_none); | |
// // Fraction is essentially equal to | |
// // 31415926535897932384626433832795028842/10000000000000000000000000000000000000 | |
// calculated_pi.set_precision(p, RoundingMode::ToEven).expect("Precision updated"); | |
// println!("Calculated pi: \n{:.41}", calculated_pi); | |
// println!("{}", cc.pi(p, RoundingMode::ToEven)); | |
// println!("Actual pi is above"); | |
} | |
EOF | |
sleep 0.1 ; | |
echo -e "\n\n##### Sleep 0.1s, then start of cargo-script output #####\n" | |
cargo +nightly -Zscript --quiet "$CARGO_SCRIPT_PATH" ; | |
( rustup default "$RUSTUP_DEFAULT" 2>&1 ) > /dev/null ; # Revert to default channel | |
unset CARGO_SCRIPT_PATH RUSTUP_DEFAULT ; | |
### End |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment