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
+23
@@ -0,0 +1,23 @@
|
||||
#!/bin/bash
|
||||
|
||||
# C++ Build Script
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== C++ Build ==="
|
||||
echo ""
|
||||
|
||||
# Kompilera C++-programmet med Boost (header-only, no linking needed)
|
||||
g++ -std=c++17 -I/opt/homebrew/opt/boost/include -o bin/print_hej src/print_hej.cpp
|
||||
|
||||
if [ $? -eq 0 ]; then
|
||||
echo "✓ Kompilering lyckades!"
|
||||
echo "Binär: bin/print_hej"
|
||||
echo ""
|
||||
echo "För att köra:"
|
||||
echo " ./bin/print_hej [decimaler]"
|
||||
else
|
||||
echo "✗ Kompilering misslyckades!"
|
||||
exit 1
|
||||
fi
|
||||
Executable
+19
@@ -0,0 +1,19 @@
|
||||
#!/bin/bash
|
||||
|
||||
# C++ Unit Tests
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "$0")/.." && pwd)"
|
||||
cd "$SCRIPT_DIR"
|
||||
|
||||
echo "=== C++ Pi-beräkning Unit Tester ==="
|
||||
echo ""
|
||||
|
||||
# Kompilera och kör pi_test
|
||||
g++ -o bin/pi_test src/pi_test.cpp -lgmp
|
||||
if [ $? -eq 0 ]; then
|
||||
./bin/pi_test
|
||||
exit $?
|
||||
else
|
||||
echo "✗ Kompilering av tester misslyckades!"
|
||||
exit 1
|
||||
fi
|
||||
@@ -0,0 +1,75 @@
|
||||
#include <gtest/gtest.h>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
const std::string SCRIPT_PATH = "/Users/einand/Code/test/cpp/print_hej";
|
||||
|
||||
std::string run_script(const std::string& args = "") {
|
||||
std::string cmd = SCRIPT_PATH;
|
||||
if (!args.empty()) {
|
||||
cmd += " " + args;
|
||||
}
|
||||
|
||||
std::array<char, 128> buffer;
|
||||
std::string result;
|
||||
std::unique_ptr<FILE, decltype(&pclose)> pipe(popen(cmd.c_str(), "r"), pclose);
|
||||
|
||||
if (!pipe) {
|
||||
throw std::runtime_error("popen() failed!");
|
||||
}
|
||||
|
||||
while (fgets(buffer.data(), buffer.size(), pipe.get()) != nullptr) {
|
||||
result += buffer.data();
|
||||
}
|
||||
|
||||
// Trim newline
|
||||
if (!result.empty() && result.back() == '\n') {
|
||||
result.pop_back();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TEST(PiTest, Test10Decimals) {
|
||||
std::string result = run_script("10");
|
||||
std::string expected = "3.1415926535";
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(PiTest, Test5Decimals) {
|
||||
std::string result = run_script("5");
|
||||
std::string expected = "3.14159";
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(PiTest, Test1Decimal) {
|
||||
std::string result = run_script("1");
|
||||
std::string expected = "3.1";
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(PiTest, Test100Decimals) {
|
||||
std::string result = run_script("100");
|
||||
std::string expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(PiTest, TestDefault100Decimals) {
|
||||
std::string result = run_script();
|
||||
std::string expected = "3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679";
|
||||
EXPECT_EQ(result, expected);
|
||||
}
|
||||
|
||||
TEST(PiTest, Test10000Decimals) {
|
||||
std::string result = run_script("10000");
|
||||
// Check length: "3." + 10000 digits = 10002 characters
|
||||
EXPECT_EQ(result.length(), 10002);
|
||||
EXPECT_TRUE(result.substr(0, 7) == "3.14159");
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
testing::InitGoogleTest(&argc, argv);
|
||||
return RUN_ALL_TESTS();
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
#include <iostream>
|
||||
#include <cstdlib>
|
||||
#include <string>
|
||||
#include <boost/multiprecision/cpp_int.hpp>
|
||||
#include <boost/multiprecision/cpp_dec_float.hpp>
|
||||
|
||||
namespace mp = boost::multiprecision;
|
||||
|
||||
// Calculate arctan(1/x) using Taylor series with arbitrary precision
|
||||
// arctan(1/x) = 1/x - 1/(3*x^3) + 1/(5*x^5) - ...
|
||||
mp::cpp_int arctan(unsigned long x, unsigned long decimals) {
|
||||
// Scale factor: 10^(decimals + 10) for precision
|
||||
mp::cpp_int scale = mp::pow(mp::cpp_int(10), decimals + 10);
|
||||
|
||||
mp::cpp_int result = 0;
|
||||
mp::cpp_int x_big = x;
|
||||
mp::cpp_int x_squared = x_big * x_big;
|
||||
|
||||
// First term: scale / x
|
||||
mp::cpp_int term = scale / x_big;
|
||||
|
||||
int sign = 1;
|
||||
unsigned long n = 0;
|
||||
|
||||
// Iterate through Taylor series
|
||||
// term_n = scale / ((2n+1) * x^(2n+1))
|
||||
// But we compute iteratively: term = term / x^2 each iteration
|
||||
while (term != 0 && n < decimals * 3) {
|
||||
// Divide by (2n+1)
|
||||
mp::cpp_int contrib = term / (2 * n + 1);
|
||||
|
||||
if (sign > 0) {
|
||||
result += contrib;
|
||||
} else {
|
||||
result -= contrib;
|
||||
}
|
||||
|
||||
// Next term: divide by x^2
|
||||
term /= x_squared;
|
||||
|
||||
sign = -sign;
|
||||
n++;
|
||||
|
||||
// Stop when term becomes negligible
|
||||
if (n > decimals * 2) break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Calculate pi using Machin's formula
|
||||
// pi/4 = 4*arctan(1/5) - arctan(1/239)
|
||||
mp::cpp_int calculate_pi(unsigned long decimals) {
|
||||
mp::cpp_int arctan_1_5 = arctan(5, decimals);
|
||||
mp::cpp_int arctan_1_239 = arctan(239, decimals);
|
||||
|
||||
// pi = 16*arctan(1/5) - 4*arctan(1/239)
|
||||
mp::cpp_int pi = 16 * arctan_1_5 - 4 * arctan_1_239;
|
||||
|
||||
return pi;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
unsigned long decimals = 100;
|
||||
|
||||
if (argc > 1) {
|
||||
decimals = std::strtoul(argv[1], nullptr, 10);
|
||||
if (decimals == 0) {
|
||||
decimals = 100;
|
||||
}
|
||||
}
|
||||
|
||||
mp::cpp_int pi = calculate_pi(decimals);
|
||||
|
||||
// Convert to string
|
||||
std::string pi_str = pi.convert_to<std::string>();
|
||||
|
||||
// Print with decimal point
|
||||
if (!pi_str.empty()) {
|
||||
std::cout << '3';
|
||||
if (decimals > 0) {
|
||||
std::cout << '.';
|
||||
// Print decimals, skipping the leading "3"
|
||||
size_t start = 1;
|
||||
size_t end = start + decimals;
|
||||
if (end > pi_str.length()) end = pi_str.length();
|
||||
for (size_t i = start; i < end && i < pi_str.length(); i++) {
|
||||
std::cout << pi_str[i];
|
||||
}
|
||||
}
|
||||
std::cout << '\n';
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
Reference in New Issue
Block a user