Initial commit: Pi calculation benchmark with 34 languages
- Added implementations for: bash, brainfuck, c, cpp, crystal, csharp, d, dart, elixir, erlang, fortran, go, haskell, java, javascript, julia, kotlin, objective-c, scala, typescript, lua, nim, odin, perl, php, python, r, ruby, rust, swift, zig, assembly, vimscript, wolfram - All implementations use Machin's formula: π/4 = 4*arctan(1/5) - arctan(1/239) - Build system with ./build.sh, test system with ./test.sh - Performance testing with ./run_all.sh - Comprehensive README.md explaining performance differences - Test framework verifies correctness against known π values
This commit is contained in:
Executable
+29
@@ -0,0 +1,29 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Rust Build Script
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== Rust Build ==="
|
||||
echo ""
|
||||
|
||||
# Kompilera Rust-programmet med cargo
|
||||
cd src
|
||||
cargo build --release
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✓ Kompilering lyckades!"
|
||||
echo "Binär: target/release/print_hej"
|
||||
echo ""
|
||||
echo "För att köra:"
|
||||
echo " ./bin/print_hej [decimaler]"
|
||||
|
||||
# Kopiera till bin/ katalogen
|
||||
mkdir -p ../bin
|
||||
cp target/release/print_hej ../bin/
|
||||
echo "Binär kopierad till: bin/print_hej"
|
||||
else
|
||||
echo "✗ Kompilering misslyckades!"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+14
@@ -0,0 +1,14 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Rust Unit Tests
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== Rust Pi-beräkning Unit Tester ==="
|
||||
echo ""
|
||||
|
||||
cd src
|
||||
cargo test
|
||||
|
||||
exit $?
|
||||
Generated
+45
@@ -0,0 +1,45 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 4
|
||||
|
||||
[[package]]
|
||||
name = "autocfg"
|
||||
version = "1.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
|
||||
|
||||
[[package]]
|
||||
name = "num-bigint"
|
||||
version = "0.4.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9"
|
||||
dependencies = [
|
||||
"num-integer",
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-integer"
|
||||
version = "0.1.46"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f"
|
||||
dependencies = [
|
||||
"num-traits",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "num-traits"
|
||||
version = "0.2.19"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841"
|
||||
dependencies = [
|
||||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "print_hej"
|
||||
version = "0.1.0"
|
||||
dependencies = [
|
||||
"num-bigint",
|
||||
"num-traits",
|
||||
]
|
||||
@@ -0,0 +1,12 @@
|
||||
[package]
|
||||
name = "print_hej"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[[bin]]
|
||||
name = "print_hej"
|
||||
path = "print_hej.rs"
|
||||
|
||||
[dependencies]
|
||||
num-bigint = "0.4"
|
||||
num-traits = "0.2"
|
||||
@@ -0,0 +1,58 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::process::Command;
|
||||
|
||||
const SCRIPT_PATH: &str = "/Users/einand/Code/test/rust/print_hej";
|
||||
|
||||
fn run_script(args: Option<&str>) -> String {
|
||||
let mut cmd = Command::new(SCRIPT_PATH);
|
||||
if let Some(arg) = args {
|
||||
cmd.arg(arg);
|
||||
}
|
||||
let output = cmd.output().expect("Failed to execute script");
|
||||
String::from_utf8_lossy(&output.stdout).trim().to_string()
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_10_decimals() {
|
||||
let result = run_script(Some("10"));
|
||||
let expected = "3.1415926535";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_5_decimals() {
|
||||
let result = run_script(Some("5"));
|
||||
let expected = "3.14159";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_1_decimal() {
|
||||
let result = run_script(Some("1"));
|
||||
let expected = "3.1";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_100_decimals() {
|
||||
let result = run_script(Some("100"));
|
||||
let expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_default_100_decimals() {
|
||||
let result = run_script(None);
|
||||
let expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
|
||||
assert_eq!(result, expected);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_10000_decimals() {
|
||||
let result = run_script(Some("10000"));
|
||||
// Check length: "3." + 10000 digits = 10002 characters
|
||||
assert_eq!(result.len(), 10002);
|
||||
assert!(result.starts_with("3.14159"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
use std::env;
|
||||
use num_bigint::BigUint;
|
||||
use num_traits::{One, Zero};
|
||||
|
||||
fn main() {
|
||||
// Hämta antal decimaler från argument
|
||||
let args: Vec<String> = env::args().collect();
|
||||
let decimals: usize = if args.len() > 1 {
|
||||
args[1].parse().unwrap_or(100)
|
||||
} else {
|
||||
100
|
||||
};
|
||||
|
||||
// Beräkna pi med Machins formel: pi/4 = 4*arctan(1/5) - arctan(1/239)
|
||||
// Använd num-bigint för exakt aritmetik
|
||||
let scale = BigUint::from(10u32).pow(decimals as u32 + 10);
|
||||
|
||||
let atan1_5 = arctan_big(5u32, &scale);
|
||||
let atan1_239 = arctan_big(239u32, &scale);
|
||||
|
||||
// 4 * atan(1/5) - atan(1/239)
|
||||
let mut result = &atan1_5 * 4u32;
|
||||
result = &result - &atan1_239;
|
||||
// * 4
|
||||
result = &result * 4u32;
|
||||
|
||||
// Skriv ut resultatet
|
||||
println!("{}", format_pi(&result, decimals));
|
||||
}
|
||||
|
||||
fn arctan_big(x: u32, scale: &BigUint) -> BigUint {
|
||||
// arctan(1/x) = 1/x - 1/(3*x^3) + 1/(5*x^5) - ...
|
||||
// Med skala: scale/x - scale/(3*x^3) + scale/(5*x^5) - ...
|
||||
|
||||
let mut result = BigUint::zero();
|
||||
let x_big = BigUint::from(x);
|
||||
let x_squared = &x_big * &x_big;
|
||||
|
||||
// term = scale / x
|
||||
let mut term = scale / &x_big;
|
||||
|
||||
let mut sign: i32 = 1;
|
||||
let mut n: u64 = 0;
|
||||
|
||||
loop {
|
||||
// term / (2n+1)
|
||||
let divisor = BigUint::from(2u64 * n + 1);
|
||||
let contrib = &term / &divisor;
|
||||
|
||||
if sign > 0 {
|
||||
result = &result + &contrib;
|
||||
} else {
|
||||
result = &result - &contrib;
|
||||
}
|
||||
|
||||
// term = term / x^2
|
||||
term = &term / &x_squared;
|
||||
|
||||
sign = -sign;
|
||||
|
||||
// Avbryt om termen är 0
|
||||
if term.is_zero() || n > 5000000 {
|
||||
break;
|
||||
}
|
||||
n += 1;
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
fn format_pi(pi: &BigUint, decimals: usize) -> String {
|
||||
// Konvertera till sträng
|
||||
let mut digits = pi.to_string();
|
||||
|
||||
// Lägg till ledande noll om nödvändigt
|
||||
while digits.len() < decimals + 10 {
|
||||
digits.insert(0, '0');
|
||||
}
|
||||
|
||||
// Ta första siffran, sedan decimalpunkt
|
||||
let int_part = &digits[0..1];
|
||||
let dec_part = &digits[1..decimals + 1];
|
||||
|
||||
format!("{}.{}", int_part, dec_part)
|
||||
}
|
||||
@@ -0,0 +1,152 @@
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::process::Command;
|
||||
|
||||
#[test]
|
||||
fn test_pi_10_decimals() {
|
||||
let output = Command::new("./print_hej")
|
||||
.arg("10")
|
||||
.output()
|
||||
.expect("Kunde inte köra program");
|
||||
|
||||
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
let expected = "3.1415926535";
|
||||
|
||||
assert_eq!(result, expected, "Fel resultat för 10 decimaler");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pi_5_decimals() {
|
||||
let output = Command::new("./print_hej")
|
||||
.arg("5")
|
||||
.output()
|
||||
.expect("Kunde inte köra program");
|
||||
|
||||
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
let expected = "3.14159";
|
||||
|
||||
assert_eq!(result, expected, "Fel resultat för 5 decimaler");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pi_1_decimal() {
|
||||
let output = Command::new("./print_hej")
|
||||
.arg("1")
|
||||
.output()
|
||||
.expect("Kunde inte köra program");
|
||||
|
||||
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
let expected = "3.1";
|
||||
|
||||
assert_eq!(result, expected, "Fel resultat för 1 decimal");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_pi_default() {
|
||||
let output = Command::new("./print_hej")
|
||||
.output()
|
||||
.expect("Kunde inte köra program");
|
||||
|
||||
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
|
||||
// Läs facit
|
||||
let facit = std::fs::read_to_string("../facit.txt")
|
||||
.expect("Kunde inte läsa facit");
|
||||
let expected: String = facit.chars().take(103).collect();
|
||||
|
||||
assert_eq!(result, expected, "Fel resultat för default (100 decimaler)");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_invalid_input() {
|
||||
let output = Command::new("./print_hej")
|
||||
.arg("abc")
|
||||
.output()
|
||||
.expect("Kunde inte köra program");
|
||||
|
||||
let result = String::from_utf8_lossy(&output.stdout).trim().to_string();
|
||||
|
||||
// Ska använda default (100 decimaler)
|
||||
assert!(result.starts_with("3.1415926535"), "Hanterar inte ogiltig input korrekt");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_calculate_pi_exact() {
|
||||
let pi = calculate_pi_exact(10);
|
||||
let result = format_pi(&pi, 10);
|
||||
|
||||
let expected = "3.1415926535";
|
||||
assert_eq!(result, expected, "calculate_pi_exact gav fel resultat");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_arctan_exact() {
|
||||
let scale = pow10(20);
|
||||
let atan1_5 = arctan_exact(5, &scale);
|
||||
|
||||
// Kontrollera att resultatet inte är tomt
|
||||
assert!(!is_zero(&atan1_5), "arctan(1/5) ska inte vara noll");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_format_pi() {
|
||||
// Skapa ett pi-värde: 31415926535... (skalat med 10^10)
|
||||
let mut pi = vec![0u32; 2];
|
||||
pi[0] = 3;
|
||||
pi[1] = 141592653;
|
||||
|
||||
let result = format_pi(&pi, 10);
|
||||
let expected = "3.141592653";
|
||||
|
||||
assert_eq!(result, expected, "format_pi gav fel resultat");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_add_big() {
|
||||
let a = vec![1, 500_000_000];
|
||||
let b = vec![2, 600_000_000];
|
||||
|
||||
let result = add_big(&a, &b);
|
||||
|
||||
// 1*10^9 + 500000000 + 2*10^9 + 600000000 = 4100000000
|
||||
// = 4 * 10^9 + 100000000
|
||||
assert_eq!(result[0], 4);
|
||||
assert_eq!(result[1], 100_000_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_subtract_big() {
|
||||
let a = vec![5, 700_000_000];
|
||||
let b = vec![2, 300_000_000];
|
||||
|
||||
let result = subtract_big(&a, &b);
|
||||
|
||||
// 5*10^9 + 700000000 - 2*10^9 - 300000000 = 3400000000
|
||||
// = 3 * 10^9 + 400000000
|
||||
assert_eq!(result[0], 3);
|
||||
assert_eq!(result[1], 400_000_000);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_multiply() {
|
||||
let a = vec![1, 500_000_000];
|
||||
|
||||
let result = multiply(&a, 2);
|
||||
|
||||
// 1*10^9 + 500000000 * 2 = 3000000000
|
||||
// = 3 * 10^9
|
||||
assert_eq!(result[0], 3);
|
||||
assert_eq!(result[1], 0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn test_divide_big() {
|
||||
let a = vec![1, 0]; // 10^9
|
||||
|
||||
let result = divide_big(&a, 2);
|
||||
|
||||
// 10^9 / 2 = 500000000
|
||||
assert_eq!(result[0], 0);
|
||||
assert_eq!(result[1], 500_000_000);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user