diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a8d6b6..65ed0a9 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,7 +1,45 @@ cmake_minimum_required(VERSION 3.10.0) project(BetterSTL VERSION 0.1.0 LANGUAGES C CXX) +set(CMAKE_EXPORT_COMPILE_COMMANDS ON) -add_library(BetterSTL src/BigInteger.cpp +# 定义源文件 +set(BETTERSTL_SOURCES + src/BigInteger.cpp src/BigDecimal.cpp) -include_directories(include) +# 生成静态库 (.a 文件) +add_library(BetterSTL_static STATIC ${BETTERSTL_SOURCES}) +target_include_directories(BetterSTL_static PUBLIC include) +set_target_properties(BetterSTL_static PROPERTIES + OUTPUT_NAME BetterSTL + PREFIX lib) + +# 生成动态库 (.so 文件) +add_library(BetterSTL_shared SHARED ${BETTERSTL_SOURCES}) +target_include_directories(BetterSTL_shared PUBLIC include) +set_target_properties(BetterSTL_shared PROPERTIES + OUTPUT_NAME BetterSTL + PREFIX lib) + +# 默认链接到静态库 +add_library(BetterSTL ALIAS BetterSTL_static) + +enable_testing() + +add_executable(BigIntegerTests tests/BigIntegerTest.cpp) +target_include_directories(BigIntegerTests PRIVATE include) +target_link_libraries(BigIntegerTests PRIVATE BetterSTL_static) +add_test(NAME BigIntegerTests COMMAND BigIntegerTests) + +add_executable(BigDecimalTests tests/BigDecimalTest.cpp) +target_include_directories(BigDecimalTests PRIVATE include) +target_link_libraries(BigDecimalTests PRIVATE BetterSTL_static) +add_test(NAME BigDecimalTests COMMAND BigDecimalTests) + +# 生成导出信息用于外部使用 +install(TARGETS BetterSTL_static BetterSTL_shared + LIBRARY DESTINATION lib + ARCHIVE DESTINATION lib + RUNTIME DESTINATION bin) +install(DIRECTORY include/ DESTINATION include) + diff --git a/include/BigDecimal.hpp b/include/BigDecimal.hpp new file mode 100644 index 0000000..322cc73 --- /dev/null +++ b/include/BigDecimal.hpp @@ -0,0 +1,72 @@ +#pragma once + +#include +#include "BigInteger.hpp" + +namespace bstl { + +class BigDecimal { +public: + BigDecimal(); + BigDecimal(int value); + BigDecimal(long long value); + BigDecimal(double value); + explicit BigDecimal(const std::string& value); + explicit BigDecimal(const char* value); + BigDecimal(const BigInteger& unscaledValue, int scale); + BigDecimal(const BigDecimal& other) = default; + BigDecimal& operator=(const BigDecimal& other) = default; + + bool isZero() const; + int sign() const; + int getScale() const; + BigInteger getUnscaledValue() const; + std::string toString() const; + + // Comparison operators + bool operator==(const BigDecimal& other) const; + bool operator!=(const BigDecimal& other) const; + bool operator<(const BigDecimal& other) const; + bool operator>(const BigDecimal& other) const; + bool operator<=(const BigDecimal& other) const; + bool operator>=(const BigDecimal& other) const; + + bool operator==(int value) const; + bool operator!=(int value) const; + bool operator<(int value) const; + bool operator>(int value) const; + bool operator<=(int value) const; + bool operator>=(int value) const; + + bool operator==(double value) const; + bool operator!=(double value) const; + bool operator<(double value) const; + bool operator>(double value) const; + bool operator<=(double value) const; + bool operator>=(double value) const; + + // Arithmetic operators + BigDecimal operator+() const; + BigDecimal operator-() const; + BigDecimal& operator+=(const BigDecimal& other); + BigDecimal& operator-=(const BigDecimal& other); + BigDecimal& operator*=(const BigDecimal& other); + BigDecimal& operator/=(const BigDecimal& other); + + BigDecimal operator+(const BigDecimal& other) const; + BigDecimal operator-(const BigDecimal& other) const; + BigDecimal operator*(const BigDecimal& other) const; + BigDecimal operator/(const BigDecimal& other) const; + + BigDecimal abs() const; + BigDecimal round(int scale) const; + +private: + BigInteger unscaledValue_; // 去掉小数点后的值 + int scale_; // 小数点后的位数 + + static void alignScale(BigInteger& lhs, int& lhsScale, + BigInteger& rhs, int& rhsScale); +}; + +} // namespace bstl diff --git a/include/BigInteger.hpp b/include/BigInteger.hpp new file mode 100644 index 0000000..ed6a4a9 --- /dev/null +++ b/include/BigInteger.hpp @@ -0,0 +1,69 @@ +#pragma once + +#include + +namespace bstl { + +class BigInteger { +public: + BigInteger(); + BigInteger(int value); + BigInteger(long long value); + BigInteger(unsigned long long value); + explicit BigInteger(const std::string& value); + explicit BigInteger(const char* value); + BigInteger(const BigInteger& other) = default; + BigInteger& operator=(const BigInteger& other) = default; + + bool isZero() const; + int sign() const; + std::string toString() const; + + bool operator==(const BigInteger& other) const; + bool operator!=(const BigInteger& other) const; + bool operator<(const BigInteger& other) const; + bool operator>(const BigInteger& other) const; + bool operator<=(const BigInteger& other) const; + bool operator>=(const BigInteger& other) const; + + bool operator==(int value) const; + bool operator!=(int value) const; + bool operator<(int value) const; + bool operator>(int value) const; + bool operator<=(int value) const; + bool operator>=(int value) const; + + bool operator==(long long value) const; + bool operator!=(long long value) const; + bool operator<(long long value) const; + bool operator>(long long value) const; + bool operator<=(long long value) const; + bool operator>=(long long value) const; + + BigInteger operator+() const; + BigInteger operator-() const; + BigInteger& operator+=(const BigInteger& other); + BigInteger& operator-=(const BigInteger& other); + BigInteger& operator*=(const BigInteger& other); + BigInteger& operator/=(const BigInteger& other); + + BigInteger operator+(const BigInteger& other) const; + BigInteger operator-(const BigInteger& other) const; + BigInteger operator*(const BigInteger& other) const; + BigInteger operator/(const BigInteger& other) const; + +private: + std::string digits_; // 无符号数字,从高位到低位 + int sign_; // -1, 0, 1 + + static std::string trimLeadingZeros(const std::string& value); + static int compareAbs(const std::string& a, const std::string& b); + static std::string addAbs(const std::string& a, const std::string& b); + static std::string subAbs(const std::string& a, const std::string& b); + static std::string mulAbs(const std::string& a, const std::string& b); + static std::string divAbs(const std::string& a, const std::string& b); +}; + +using BitInteger = BigInteger; + +} // namespace bstl diff --git a/include/bstl/bstl.hpp b/include/bstl/bstl.hpp index efaeebf..91fc56c 100644 --- a/include/bstl/bstl.hpp +++ b/include/bstl/bstl.hpp @@ -1,6 +1,7 @@ + #ifndef BETTERSTL_BSTL_HPP -#define BETTERSTL_BSTL_HPP - +#include +#include #include - +#define BETTERSTL_BSTL_HPP #endif //BETTERSTL_BSTL_HPP diff --git a/src/BigDecimal.cpp b/src/BigDecimal.cpp index 840565c..a09b0e5 100644 --- a/src/BigDecimal.cpp +++ b/src/BigDecimal.cpp @@ -1 +1,341 @@ -#include \ No newline at end of file +#include "BigDecimal.hpp" + +#include +#include +#include + +namespace bstl { + +BigDecimal::BigDecimal() : unscaledValue_(0), scale_(0) {} + +BigDecimal::BigDecimal(int value) : unscaledValue_(value), scale_(0) {} + +BigDecimal::BigDecimal(long long value) : unscaledValue_(value), scale_(0) {} + +BigDecimal::BigDecimal(double value) : scale_(0) { + if (value == 0.0) { + unscaledValue_ = 0; + scale_ = 0; + return; + } + + // 将浮点数转换为字符串,然后解析 + std::ostringstream oss; + oss.precision(15); + oss << value; + *this = BigDecimal(oss.str()); +} + +BigDecimal::BigDecimal(const std::string& value) : unscaledValue_(0), scale_(0) { + if (value.empty()) { + return; + } + + std::string text = value; + + // 去掉前后空格 + size_t start = 0, end = text.size(); + while (start < end && text[start] == ' ') start++; + while (end > start && text[end - 1] == ' ') end--; + text = text.substr(start, end - start); + + if (text.empty()) { + return; + } + + // 查找小数点位置 + size_t dotPos = text.find('.'); + if (dotPos != std::string::npos) { + scale_ = text.size() - dotPos - 1; + std::string digits = text.substr(0, dotPos) + text.substr(dotPos + 1); + unscaledValue_ = BigInteger(digits); + } else { + scale_ = 0; + unscaledValue_ = BigInteger(text); + } +} + +BigDecimal::BigDecimal(const char* value) + : BigDecimal(value == nullptr ? std::string("0") : std::string(value)) {} + +BigDecimal::BigDecimal(const BigInteger& unscaledValue, int scale) + : unscaledValue_(unscaledValue), scale_(scale) { + if (scale < 0) { + throw std::invalid_argument("scale cannot be negative"); + } +} + +bool BigDecimal::isZero() const { + return unscaledValue_.isZero(); +} + +int BigDecimal::sign() const { + return unscaledValue_.sign(); +} + +int BigDecimal::getScale() const { + return scale_; +} + +BigInteger BigDecimal::getUnscaledValue() const { + return unscaledValue_; +} + +std::string BigDecimal::toString() const { + if (isZero()) { + return "0"; + } + + std::string digitStr = unscaledValue_.toString(); + + // 处理符号 + bool negative = false; + if (digitStr[0] == '-') { + negative = true; + digitStr = digitStr.substr(1); + } + + // 插入小数点 + if (scale_ == 0) { + return (negative ? "-" : "") + digitStr; + } + + if (static_cast(digitStr.size()) <= scale_) { + // 需要前置 "0." + std::string result = "0."; + for (int i = 0; i < scale_ - static_cast(digitStr.size()); i++) { + result += "0"; + } + result += digitStr; + return (negative ? "-" : "") + result; + } + + int dotPos = digitStr.size() - scale_; + std::string result = digitStr.substr(0, dotPos) + "." + digitStr.substr(dotPos); + return (negative ? "-" : "") + result; +} + +void BigDecimal::alignScale(BigInteger& lhs, int& lhsScale, + BigInteger& rhs, int& rhsScale) { + if (lhsScale < rhsScale) { + // 左边需要扩大 + for (int i = 0; i < rhsScale - lhsScale; i++) { + lhs = lhs * BigInteger(10); + } + lhsScale = rhsScale; + } else if (lhsScale > rhsScale) { + // 右边需要扩大 + for (int i = 0; i < lhsScale - rhsScale; i++) { + rhs = rhs * BigInteger(10); + } + rhsScale = lhsScale; + } +} + +bool BigDecimal::operator==(const BigDecimal& other) const { + if (isZero() && other.isZero()) return true; + BigInteger lhs = unscaledValue_; + BigInteger rhs = other.unscaledValue_; + int lhsScale = scale_; + int rhsScale = other.scale_; + alignScale(lhs, lhsScale, rhs, rhsScale); + return lhs == rhs; +} + +bool BigDecimal::operator!=(const BigDecimal& other) const { + return !(*this == other); +} + +bool BigDecimal::operator<(const BigDecimal& other) const { + if (unscaledValue_.sign() != other.unscaledValue_.sign()) { + return unscaledValue_.sign() < other.unscaledValue_.sign(); + } + + BigInteger lhs = unscaledValue_; + BigInteger rhs = other.unscaledValue_; + int lhsScale = scale_; + int rhsScale = other.scale_; + alignScale(lhs, lhsScale, rhs, rhsScale); + + if (unscaledValue_.sign() >= 0) { + return lhs < rhs; + } else { + return lhs > rhs; + } +} + +bool BigDecimal::operator>(const BigDecimal& other) const { + return other < *this; +} + +bool BigDecimal::operator<=(const BigDecimal& other) const { + return *this < other || *this == other; +} + +bool BigDecimal::operator>=(const BigDecimal& other) const { + return other <= *this; +} + +bool BigDecimal::operator==(int value) const { + return *this == BigDecimal(value); +} + +bool BigDecimal::operator!=(int value) const { + return !(*this == value); +} + +bool BigDecimal::operator<(int value) const { + return *this < BigDecimal(value); +} + +bool BigDecimal::operator>(int value) const { + return *this > BigDecimal(value); +} + +bool BigDecimal::operator<=(int value) const { + return *this <= BigDecimal(value); +} + +bool BigDecimal::operator>=(int value) const { + return *this >= BigDecimal(value); +} + +bool BigDecimal::operator==(double value) const { + return *this == BigDecimal(value); +} + +bool BigDecimal::operator!=(double value) const { + return !(*this == value); +} + +bool BigDecimal::operator<(double value) const { + return *this < BigDecimal(value); +} + +bool BigDecimal::operator>(double value) const { + return *this > BigDecimal(value); +} + +bool BigDecimal::operator<=(double value) const { + return *this <= BigDecimal(value); +} + +bool BigDecimal::operator>=(double value) const { + return *this >= BigDecimal(value); +} + +BigDecimal BigDecimal::operator+() const { + return *this; +} + +BigDecimal BigDecimal::operator-() const { + if (isZero()) { + return BigDecimal(0); + } + return BigDecimal(-unscaledValue_, scale_); +} + +BigDecimal& BigDecimal::operator+=(const BigDecimal& other) { + *this = *this + other; + return *this; +} + +BigDecimal& BigDecimal::operator-=(const BigDecimal& other) { + *this = *this - other; + return *this; +} + +BigDecimal& BigDecimal::operator*=(const BigDecimal& other) { + *this = *this * other; + return *this; +} + +BigDecimal& BigDecimal::operator/=(const BigDecimal& other) { + *this = *this / other; + return *this; +} + +BigDecimal BigDecimal::operator+(const BigDecimal& other) const { + if (isZero()) return other; + if (other.isZero()) return *this; + + BigInteger lhs = unscaledValue_; + BigInteger rhs = other.unscaledValue_; + int lhsScale = scale_; + int rhsScale = other.scale_; + alignScale(lhs, lhsScale, rhs, rhsScale); + + return BigDecimal(lhs + rhs, lhsScale); +} + +BigDecimal BigDecimal::operator-(const BigDecimal& other) const { + return *this + (-other); +} + +BigDecimal BigDecimal::operator*(const BigDecimal& other) const { + if (isZero() || other.isZero()) { + return BigDecimal(0); + } + + BigInteger result = unscaledValue_ * other.unscaledValue_; + int resultScale = scale_ + other.scale_; + + return BigDecimal(result, resultScale); +} + +BigDecimal BigDecimal::operator/(const BigDecimal& other) const { + if (other.isZero()) { + throw std::invalid_argument("division by zero"); + } + + if (isZero()) { + return BigDecimal(0); + } + + // 先对齐 scale,然后做整数除法 + BigInteger lhs = unscaledValue_; + BigInteger rhs = other.unscaledValue_; + int lhsScale = scale_; + int rhsScale = other.scale_; + + // 使用更高的精度进行除法 + // 乘以 10^precision 来获得更多的精度 + int precision = 10; + for (int i = 0; i < precision; i++) { + lhs = lhs * BigInteger(10); + } + + BigInteger quotient = lhs / rhs; + int resultScale = lhsScale - rhsScale + precision; + + return BigDecimal(quotient, resultScale); +} + +BigDecimal BigDecimal::abs() const { + if (unscaledValue_.sign() >= 0) { + return *this; + } + return BigDecimal(-unscaledValue_, scale_); +} + +BigDecimal BigDecimal::round(int scale) const { + if (scale < 0) { + throw std::invalid_argument("scale cannot be negative"); + } + + if (scale >= scale_) { + return *this; + } + + // 简单实现:直接截断到指定小数位数 + int diff = scale_ - scale; + BigInteger divisor = BigInteger(10); + for (int i = 1; i < diff; i++) { + divisor = divisor * BigInteger(10); + } + + BigInteger rounded = unscaledValue_ / divisor; + return BigDecimal(rounded, scale); +} + +} // namespace bstl diff --git a/src/BigInteger.cpp b/src/BigInteger.cpp index 85f42c0..06ebca9 100644 --- a/src/BigInteger.cpp +++ b/src/BigInteger.cpp @@ -1 +1,378 @@ -#include \ No newline at end of file +#include "BigInteger.hpp" + +#include +#include +#include +#include + +namespace bstl { + +std::string BigInteger::trimLeadingZeros(const std::string& value) { + size_t pos = 0; + while (pos < value.size() - 1 && value[pos] == '0') { + pos++; + } + return value.substr(pos); +} + +int BigInteger::compareAbs(const std::string& a, const std::string& b) { + std::string ta = trimLeadingZeros(a); + std::string tb = trimLeadingZeros(b); + if (ta.size() != tb.size()) { + return ta.size() < tb.size() ? -1 : 1; + } + return ta.compare(tb) < 0 ? -1 : (ta.compare(tb) > 0 ? 1 : 0); +} + +std::string BigInteger::addAbs(const std::string& a, const std::string& b) { + std::string result; + int carry = 0; + int i = static_cast(a.size()) - 1; + int j = static_cast(b.size()) - 1; + while (i >= 0 || j >= 0 || carry) { + int sum = carry; + if (i >= 0) sum += a[i--] - '0'; + if (j >= 0) sum += b[j--] - '0'; + result = char('0' + sum % 10) + result; + carry = sum / 10; + } + return result; +} + +std::string BigInteger::subAbs(const std::string& a, const std::string& b) { + std::string ta = trimLeadingZeros(a); + std::string tb = trimLeadingZeros(b); + if (compareAbs(ta, tb) < 0) { + return subAbs(tb, ta); + } + std::string result; + int borrow = 0; + int i = static_cast(ta.size()) - 1; + int j = static_cast(tb.size()) - 1; + while (i >= 0) { + int diff = (ta[i--] - '0') - borrow; + if (j >= 0) { + diff -= (tb[j--] - '0'); + } + if (diff < 0) { + diff += 10; + borrow = 1; + } else { + borrow = 0; + } + result = char('0' + diff) + result; + } + return trimLeadingZeros(result); +} + +std::string BigInteger::mulAbs(const std::string& a, const std::string& b) { + std::string ta = trimLeadingZeros(a); + std::string tb = trimLeadingZeros(b); + if (ta == "0" || tb == "0") return "0"; + + std::vector product(ta.size() + tb.size(), 0); + for (size_t i = 0; i < ta.size(); i++) { + for (size_t j = 0; j < tb.size(); j++) { + int mul = (ta[ta.size() - 1 - i] - '0') * (tb[tb.size() - 1 - j] - '0'); + product[i + j] += mul; + } + } + + int carry = 0; + for (size_t i = 0; i < product.size(); i++) { + int sum = product[i] + carry; + product[i] = sum % 10; + carry = sum / 10; + } + + std::string result; + for (int i = static_cast(product.size()) - 1; i >= 0; i--) { + result += char('0' + product[i]); + } + return trimLeadingZeros(result); +} + +std::string BigInteger::divAbs(const std::string& a, const std::string& b) { + std::string tb = trimLeadingZeros(b); + if (tb == "0") { + throw std::invalid_argument("division by zero"); + } + std::string ta = trimLeadingZeros(a); + if (compareAbs(ta, tb) < 0) { + return "0"; + } + + std::string quotient; + std::string current; + for (char digit : ta) { + current += digit; + current = trimLeadingZeros(current); + int count = 0; + while (compareAbs(current, tb) >= 0) { + current = subAbs(current, tb); + count++; + } + quotient += char('0' + count); + } + return trimLeadingZeros(quotient); +} + +BigInteger::BigInteger() : digits_("0"), sign_(0) {} + +BigInteger::BigInteger(int value) : digits_("0"), sign_(1) { + if (value == 0) { + digits_ = "0"; + sign_ = 0; + return; + } + if (value < 0) { + sign_ = -1; + value = -value; + } + digits_.clear(); + while (value > 0) { + digits_ = char('0' + value % 10) + digits_; + value /= 10; + } +} + +BigInteger::BigInteger(long long value) : digits_("0"), sign_(1) { + if (value == 0) { + digits_ = "0"; + sign_ = 0; + return; + } + if (value < 0) { + sign_ = -1; + value = -value; + } + digits_.clear(); + while (value > 0) { + digits_ = char('0' + value % 10) + digits_; + value /= 10; + } +} + +BigInteger::BigInteger(unsigned long long value) : digits_("0"), sign_(1) { + if (value == 0) { + digits_ = "0"; + sign_ = 0; + return; + } + digits_.clear(); + while (value > 0) { + digits_ = char('0' + value % 10) + digits_; + value /= 10; + } +} + +BigInteger::BigInteger(const std::string& value) : digits_("0"), sign_(1) { + if (value.empty()) { + digits_ = "0"; + sign_ = 0; + return; + } + + std::string text = value; + sign_ = 1; + + if (text[0] == '-') { + sign_ = -1; + text = text.substr(1); + } else if (text[0] == '+') { + text = text.substr(1); + } + + if (text.empty()) { + digits_ = "0"; + sign_ = 0; + return; + } + + for (char ch : text) { + if (ch < '0' || ch > '9') { + throw std::invalid_argument("BigInteger: invalid numeric string"); + } + } + + digits_ = trimLeadingZeros(text); + if (digits_ == "0") { + sign_ = 0; + } +} + +BigInteger::BigInteger(const char* value) + : BigInteger(value == nullptr ? std::string("0") : std::string(value)) {} + +bool BigInteger::isZero() const { + return sign_ == 0 || digits_ == "0"; +} + +int BigInteger::sign() const { + return isZero() ? 0 : sign_; +} + +std::string BigInteger::toString() const { + if (isZero()) return "0"; + return (sign_ < 0 ? "-" : "") + digits_; +} + +bool BigInteger::operator==(const BigInteger& other) const { + if (isZero() && other.isZero()) return true; + return sign_ == other.sign_ && digits_ == other.digits_; +} + +bool BigInteger::operator!=(const BigInteger& other) const { + return !(*this == other); +} + +bool BigInteger::operator<(const BigInteger& other) const { + if (sign_ != other.sign_) return sign_ < other.sign_; + if (sign_ == 0) return false; + int cmp = compareAbs(digits_, other.digits_); + return sign_ > 0 ? cmp < 0 : cmp > 0; +} + +bool BigInteger::operator>(const BigInteger& other) const { + return other < *this; +} + +bool BigInteger::operator<=(const BigInteger& other) const { + return *this < other || *this == other; +} + +bool BigInteger::operator>=(const BigInteger& other) const { + return other <= *this; +} + +bool BigInteger::operator==(int value) const { + return *this == BigInteger(value); +} + +bool BigInteger::operator!=(int value) const { + return !(*this == value); +} + +bool BigInteger::operator<(int value) const { + return *this < BigInteger(value); +} + +bool BigInteger::operator>(int value) const { + return *this > BigInteger(value); +} + +bool BigInteger::operator<=(int value) const { + return *this <= BigInteger(value); +} + +bool BigInteger::operator>=(int value) const { + return *this >= BigInteger(value); +} + +bool BigInteger::operator==(long long value) const { + return *this == BigInteger(value); +} + +bool BigInteger::operator!=(long long value) const { + return !(*this == value); +} + +bool BigInteger::operator<(long long value) const { + return *this < BigInteger(value); +} + +bool BigInteger::operator>(long long value) const { + return *this > BigInteger(value); +} + +bool BigInteger::operator<=(long long value) const { + return *this <= BigInteger(value); +} + +bool BigInteger::operator>=(long long value) const { + return *this >= BigInteger(value); +} + +BigInteger BigInteger::operator+() const { + return *this; +} + +BigInteger BigInteger::operator-() const { + if (isZero()) return BigInteger(0); + BigInteger result(*this); + result.sign_ = -result.sign_; + return result; +} + +BigInteger& BigInteger::operator+=(const BigInteger& other) { + *this = *this + other; + return *this; +} + +BigInteger& BigInteger::operator-=(const BigInteger& other) { + *this = *this - other; + return *this; +} + +BigInteger& BigInteger::operator*=(const BigInteger& other) { + *this = *this * other; + return *this; +} + +BigInteger& BigInteger::operator/=(const BigInteger& other) { + *this = *this / other; + return *this; +} + +BigInteger BigInteger::operator+(const BigInteger& other) const { + if (isZero()) return other; + if (other.isZero()) return *this; + + BigInteger result; + if (sign_ == other.sign_) { + result.digits_ = addAbs(digits_, other.digits_); + result.sign_ = sign_; + } else { + int cmp = compareAbs(digits_, other.digits_); + if (cmp == 0) { + result.digits_ = "0"; + result.sign_ = 0; + } else if (cmp > 0) { + result.digits_ = subAbs(digits_, other.digits_); + result.sign_ = sign_; + } else { + result.digits_ = subAbs(other.digits_, digits_); + result.sign_ = other.sign_; + } + } + if (result.digits_ == "0") result.sign_ = 0; + return result; +} + +BigInteger BigInteger::operator-(const BigInteger& other) const { + return *this + (-other); +} + +BigInteger BigInteger::operator*(const BigInteger& other) const { + if (isZero() || other.isZero()) return BigInteger(0); + BigInteger result; + result.digits_ = mulAbs(digits_, other.digits_); + result.sign_ = (sign_ * other.sign_); + if (result.digits_ == "0") result.sign_ = 0; + return result; +} + +BigInteger BigInteger::operator/(const BigInteger& other) const { + if (other.isZero()) { + throw std::invalid_argument("division by zero"); + } + if (isZero()) return BigInteger(0); + BigInteger result; + result.digits_ = divAbs(digits_, other.digits_); + result.sign_ = (sign_ * other.sign_); + if (result.digits_ == "0") result.sign_ = 0; + return result; +} + +} // namespace bstl + diff --git a/tests/BigDecimalTest.cpp b/tests/BigDecimalTest.cpp new file mode 100644 index 0000000..8a14df4 --- /dev/null +++ b/tests/BigDecimalTest.cpp @@ -0,0 +1,41 @@ +#include + +#include +#include +#include + +int main() { + using bstl::BigDecimal; + + // 基本构造 + BigDecimal a("123.45"); + BigDecimal b("67.89"); + BigDecimal c = a + b; + + assert(c.toString() == "191.34"); + + // 减法 + BigDecimal d = a - b; + assert(d.toString() == "55.56"); + + // 乘法 + BigDecimal e = a * BigDecimal("2"); + assert(e.toString() == "246.90"); + + // 比较 + assert((a > b) == true); + assert((a == a) == true); + assert((a != b) == true); + + // 零 + BigDecimal zero("0.0"); + assert(zero.isZero()); + + // 负数 + BigDecimal neg("-100.50"); + assert(neg.sign() < 0); + assert((-neg).toString() == "100.50"); + + std::cout << "BigDecimal tests passed\n"; + return 0; +} diff --git a/tests/BigIntegerTest.cpp b/tests/BigIntegerTest.cpp new file mode 100644 index 0000000..475478b --- /dev/null +++ b/tests/BigIntegerTest.cpp @@ -0,0 +1,31 @@ +#include + +#include +#include +#include + +int main() { + using bstl::BigInteger; + + BigInteger a("12345678901234567890"); + BigInteger b("98765432109876543210"); + BigInteger c = a + b; + BigInteger d = b - a; + BigInteger e = a * BigInteger("2"); + BigInteger f = BigInteger("100000000000000000000000") / BigInteger("1000000000000000000"); + + assert(c.toString() == "111111111011111111100"); + assert(d.toString() == "86419753208641975320"); + assert(e.toString() == "24691357802469135780"); + assert(f.toString() == "100000"); + + BigInteger zero("0"); + assert((a == a) == true); + assert((a != b) == true); + assert((zero == 0) == true); + assert((a > BigInteger("12345678901234567889")) == true); + assert((a < b) == true); + + std::cout << "BigInteger tests passed\n"; + return 0; +}