2 Commits
Author SHA256 Message Date
ArchZer0 202767a608 高精度改为vector 2026-08-16 19:23:09 +08:00
ArchZer0 2a6c53d5bf 统一命名 2026-08-16 19:15:19 +08:00
8 changed files with 580 additions and 391 deletions
+145
View File
@@ -0,0 +1,145 @@
# Generated from CLion Inspection settings
---
Checks: '-*,
bugprone-argument-comment,
bugprone-assert-side-effect,
bugprone-bad-signal-to-kill-thread,
bugprone-branch-clone,
bugprone-copy-constructor-init,
bugprone-dangling-handle,
bugprone-dynamic-static-initializers,
bugprone-fold-init-type,
bugprone-forward-declaration-namespace,
bugprone-forwarding-reference-overload,
bugprone-inaccurate-erase,
bugprone-incorrect-roundings,
bugprone-integer-division,
bugprone-lambda-function-name,
bugprone-macro-parentheses,
bugprone-macro-repeated-side-effects,
bugprone-misplaced-operator-in-strlen-in-alloc,
bugprone-misplaced-pointer-arithmetic-in-alloc,
bugprone-misplaced-widening-cast,
bugprone-move-forwarding-reference,
bugprone-multiple-statement-macro,
bugprone-no-escape,
bugprone-parent-virtual-call,
bugprone-posix-return,
bugprone-reserved-identifier,
bugprone-sizeof-container,
bugprone-sizeof-expression,
bugprone-spuriously-wake-up-functions,
bugprone-string-constructor,
bugprone-string-integer-assignment,
bugprone-string-literal-with-embedded-nul,
bugprone-suspicious-enum-usage,
bugprone-suspicious-include,
bugprone-suspicious-memset-usage,
bugprone-suspicious-missing-comma,
bugprone-suspicious-semicolon,
bugprone-suspicious-string-compare,
bugprone-suspicious-memory-comparison,
bugprone-suspicious-realloc-usage,
bugprone-swapped-arguments,
bugprone-terminating-continue,
bugprone-throw-keyword-missing,
bugprone-too-small-loop-variable,
bugprone-undefined-memory-manipulation,
bugprone-undelegated-constructor,
bugprone-unhandled-self-assignment,
bugprone-unused-raii,
bugprone-unused-return-value,
bugprone-use-after-move,
bugprone-virtual-near-miss,
cert-dcl21-cpp,
cert-dcl58-cpp,
cert-err34-c,
cert-err52-cpp,
cert-err60-cpp,
cert-flp30-c,
cert-msc50-cpp,
cert-msc51-cpp,
cert-str34-c,
cppcoreguidelines-interfaces-global-init,
cppcoreguidelines-narrowing-conversions,
cppcoreguidelines-pro-type-member-init,
cppcoreguidelines-pro-type-static-cast-downcast,
cppcoreguidelines-slicing,
google-default-arguments,
google-runtime-operator,
hicpp-exception-baseclass,
hicpp-multiway-paths-covered,
misc-misplaced-const,
misc-new-delete-overloads,
misc-non-copyable-objects,
misc-throw-by-value-catch-by-reference,
misc-unconventional-assign-operator,
misc-uniqueptr-reset-release,
modernize-avoid-bind,
modernize-concat-nested-namespaces,
modernize-deprecated-headers,
modernize-deprecated-ios-base-aliases,
modernize-loop-convert,
modernize-make-shared,
modernize-make-unique,
modernize-pass-by-value,
modernize-raw-string-literal,
modernize-redundant-void-arg,
modernize-replace-auto-ptr,
modernize-replace-disallow-copy-and-assign-macro,
modernize-replace-random-shuffle,
modernize-return-braced-init-list,
modernize-shrink-to-fit,
modernize-unary-static-assert,
modernize-use-auto,
modernize-use-bool-literals,
modernize-use-emplace,
modernize-use-equals-default,
modernize-use-equals-delete,
modernize-use-nodiscard,
modernize-use-noexcept,
modernize-use-nullptr,
modernize-use-override,
modernize-use-transparent-functors,
modernize-use-uncaught-exceptions,
mpi-buffer-deref,
mpi-type-mismatch,
openmp-use-default-none,
performance-faster-string-find,
performance-for-range-copy,
performance-implicit-conversion-in-loop,
performance-inefficient-algorithm,
performance-inefficient-string-concatenation,
performance-inefficient-vector-operation,
performance-move-const-arg,
performance-move-constructor-init,
performance-no-automatic-move,
performance-noexcept-move-constructor,
performance-trivially-destructible,
performance-type-promotion-in-math-fn,
performance-unnecessary-copy-initialization,
performance-unnecessary-value-param,
portability-simd-intrinsics,
readability-avoid-const-params-in-decls,
readability-const-return-type,
readability-container-size-empty,
readability-convert-member-functions-to-static,
readability-delete-null-pointer,
readability-deleted-default,
readability-inconsistent-declaration-parameter-name,
readability-make-member-function-const,
readability-misleading-indentation,
readability-misplaced-array-index,
readability-non-const-parameter,
readability-redundant-control-flow,
readability-redundant-declaration,
readability-redundant-function-ptr-dereference,
readability-redundant-smartptr-get,
readability-redundant-string-cstr,
readability-redundant-string-init,
readability-simplify-subscript-expr,
readability-static-accessed-through-instance,
readability-static-definition-in-anonymous-namespace,
readability-string-compare,
readability-uniqueptr-delete-release,
readability-use-anyofallof'
+10 -10
View File
@@ -18,11 +18,11 @@ public:
BigDecimal(const BigDecimal& other) = default; BigDecimal(const BigDecimal& other) = default;
BigDecimal& operator=(const BigDecimal& other) = default; BigDecimal& operator=(const BigDecimal& other) = default;
bool isZero() const; [[nodiscard]] bool isZero() const;
int sign() const; [[nodiscard]] int sign() const;
int getScale() const; [[nodiscard]] int getScale() const;
BigInteger getUnscaledValue() const; [[nodiscard]] BigInteger getUnscaledValue() const;
std::string toString() const; [[nodiscard]] std::string toString() const;
// Comparison operators // Comparison operators
bool operator==(const BigDecimal& other) const; bool operator==(const BigDecimal& other) const;
@@ -59,14 +59,14 @@ public:
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; [[nodiscard]] BigDecimal abs() const;
BigDecimal round(int scale) const; [[nodiscard]] BigDecimal round(int scale) const;
private: private:
BigInteger unscaledValue_; // 去掉小数点后的值 BigInteger m_unscaledValue; // 去掉小数点后的值
int scale_; // 小数点后的位数 int m_scale; // 小数点后的位数
static void alignScale(BigInteger& lhs, int& lhsScale, static void m_alignScale(BigInteger& lhs, int& lhsScale,
BigInteger& rhs, int& rhsScale); BigInteger& rhs, int& rhsScale);
}; };
+12 -11
View File
@@ -2,6 +2,7 @@
#define BETTERSTL_BIG_INTEGER_HPP #define BETTERSTL_BIG_INTEGER_HPP
#include <string> #include <string>
#include <vector>
#include <iostream> #include <iostream>
namespace bstl { namespace bstl {
@@ -17,9 +18,9 @@ public:
BigInteger(const BigInteger& other) = default; BigInteger(const BigInteger& other) = default;
BigInteger& operator=(const BigInteger& other) = default; BigInteger& operator=(const BigInteger& other) = default;
bool isZero() const; [[nodiscard]] bool isZero() const;
int sign() const; [[nodiscard]] int sign() const;
std::string toString() const; [[nodiscard]] 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;
@@ -55,15 +56,15 @@ public:
BigInteger operator/(const BigInteger& other) const; BigInteger operator/(const BigInteger& other) const;
private: private:
std::string digits_; // 无符号数字,从高位到低位 std::vector<int> m_digits; // 无符号数字,低位在前
int sign_; // -1, 0, 1 int m_sign; // -1, 0, 1
static std::string trimLeadingZeros(const std::string& value); static std::vector<int> m_trimLeadingZeros(const std::vector<int>& value);
static int compareAbs(const std::string& a, const std::string& b); static int m_compareAbs(const std::vector<int>& a, const std::vector<int>& b);
static std::string addAbs(const std::string& a, const std::string& b); static std::vector<int> m_addAbs(const std::vector<int>& a, const std::vector<int>& b);
static std::string subAbs(const std::string& a, const std::string& b); static std::vector<int> m_subAbs(const std::vector<int>& a, const std::vector<int>& b);
static std::string mulAbs(const std::string& a, const std::string& b); static std::vector<int> m_mulAbs(const std::vector<int>& a, const std::vector<int>& b);
static std::string divAbs(const std::string& a, const std::string& b); static std::vector<int> m_divAbs(const std::vector<int>& a, const std::vector<int>& b);
}; };
// 流运算符重载 // 流运算符重载
+36 -36
View File
@@ -11,69 +11,69 @@ namespace bstl {
class String { class String {
public: public:
String(); String();
String(const std::string& str); String(std::string str);
String(const char* str); String(const char* str);
String(const String& other) = default; String(const String& other) = default;
String& operator=(const String& other) = default; String& operator=(const String& other) = default;
// 获取标准字符串 // 获取标准字符串
std::string str() const; [[nodiscard]] std::string str() const;
const char* c_str() const; [[nodiscard]] const char* c_str() const;
size_t length() const; [[nodiscard]] size_t length() const;
size_t size() const; [[nodiscard]] size_t size() const;
bool empty() const; [[nodiscard]] bool empty() const;
// 获取/修改字符 // 获取/修改字符
char at(size_t pos) const; [[nodiscard]] char at(size_t pos) const;
char operator[](size_t pos) const; char operator[](size_t pos) const;
char& operator[](size_t pos); char& operator[](size_t pos);
// 分割 - 按分隔符分割字符串 // 分割 - 按分隔符分割字符串
std::vector<String> split(const String& delimiter = " ") const; [[nodiscard]] std::vector<String> split(const String& delimiter = " ") const;
// 连接 - 用分隔符连接多个字符串 // 连接 - 用分隔符连接多个字符串
static String join(const std::vector<String>& parts, const String& delimiter = ""); static String join(const std::vector<String>& parts, const String& delimiter = "");
// 替换 - 替换第一个/所有匹配项 // 替换 - 替换第一个/所有匹配项
String replace(const String& oldStr, const String& newStr, int count = -1) const; [[nodiscard]] String replace(const String& oldStr, const String& newStr, int count = -1) const;
// 大小写转换 // 大小写转换
String upper() const; [[nodiscard]] String upper() const;
String lower() const; [[nodiscard]] String lower() const;
String capitalize() const; // 首字母大写 [[nodiscard]] String capitalize() const; // 首字母大写
String title() const; // 每个单词首字母大写 [[nodiscard]] String title() const; // 每个单词首字母大写
// 判断函数 // 判断函数
bool startswith(const String& prefix) const; [[nodiscard]] bool startswith(const String& prefix) const;
bool endswith(const String& suffix) const; [[nodiscard]] bool endswith(const String& suffix) const;
bool contains(const String& substring) const; [[nodiscard]] bool contains(const String& substring) const;
bool isdigit() const; [[nodiscard]] bool isdigit() const;
bool isalpha() const; [[nodiscard]] bool isalpha() const;
bool isalnum() const; [[nodiscard]] bool isalnum() const;
bool isspace() const; [[nodiscard]] bool isspace() const;
bool isupper() const; [[nodiscard]] bool isupper() const;
bool islower() const; [[nodiscard]] bool islower() const;
// 查找和计数 // 查找和计数
int find(const String& substring, size_t start = 0) const; [[nodiscard]] int find(const String& substring, size_t start = 0) const;
int rfind(const String& substring) const; // 从后往前查找 [[nodiscard]] int rfind(const String& substring) const; // 从后往前查找
int count(const String& substring) const; [[nodiscard]] int count(const String& substring) const;
// 去除空格和其他字符 // 去除空格和其他字符
String strip() const; // 去除前后空格 [[nodiscard]] String strip() const; // 去除前后空格
String lstrip() const; // 去除前导空格 [[nodiscard]] String lstrip() const; // 去除前导空格
String rstrip() const; // 去除尾部空格 [[nodiscard]] String rstrip() const; // 去除尾部空格
String strip(const String& chars) const; // 去除指定字符 [[nodiscard]] String strip(const String& chars) const; // 去除指定字符
// 对齐和填充 // 对齐和填充
String ljust(size_t width, char fillchar = ' ') const; [[nodiscard]] String ljust(size_t width, char fillchar = ' ') const;
String rjust(size_t width, char fillchar = ' ') const; [[nodiscard]] String rjust(size_t width, char fillchar = ' ') const;
String center(size_t width, char fillchar = ' ') const; [[nodiscard]] String center(size_t width, char fillchar = ' ') const;
// 字符串转换 // 字符串转换
int toInt() const; [[nodiscard]] int toInt() const;
long long toLongLong() const; [[nodiscard]] long long toLongLong() const;
double toDouble() const; [[nodiscard]] double toDouble() const;
// 运算符重载 // 运算符重载
String operator+(const String& other) const; String operator+(const String& other) const;
@@ -87,7 +87,7 @@ public:
bool operator>=(const String& other) const; bool operator>=(const String& other) const;
private: private:
std::string data_; std::string m_data;
}; };
// 流运算符重载 // 流运算符重载
+59 -59
View File
@@ -6,16 +6,16 @@
namespace bstl { namespace bstl {
BigDecimal::BigDecimal() : unscaledValue_(0), scale_(0) {} BigDecimal::BigDecimal() : m_unscaledValue(0), m_scale(0) {}
BigDecimal::BigDecimal(int value) : unscaledValue_(value), scale_(0) {} BigDecimal::BigDecimal(int value) : m_unscaledValue(value), m_scale(0) {}
BigDecimal::BigDecimal(long long value) : unscaledValue_(value), scale_(0) {} BigDecimal::BigDecimal(long long value) : m_unscaledValue(value), m_scale(0) {}
BigDecimal::BigDecimal(double value) : scale_(0) { BigDecimal::BigDecimal(double value) : m_scale(0) {
if (value == 0.0) { if (value == 0.0) {
unscaledValue_ = 0; m_unscaledValue = 0;
scale_ = 0; m_scale = 0;
return; return;
} }
@@ -26,7 +26,7 @@ BigDecimal::BigDecimal(double value) : scale_(0) {
*this = BigDecimal(oss.str()); *this = BigDecimal(oss.str());
} }
BigDecimal::BigDecimal(const std::string& value) : unscaledValue_(0), scale_(0) { BigDecimal::BigDecimal(const std::string& value) : m_unscaledValue(0), m_scale(0) {
if (value.empty()) { if (value.empty()) {
return; return;
} }
@@ -46,12 +46,12 @@ BigDecimal::BigDecimal(const std::string& value) : unscaledValue_(0), scale_(0)
// 查找小数点位置 // 查找小数点位置
size_t dotPos = text.find('.'); size_t dotPos = text.find('.');
if (dotPos != std::string::npos) { if (dotPos != std::string::npos) {
scale_ = text.size() - dotPos - 1; m_scale = static_cast<int>(text.size() - dotPos - 1);
std::string digits = text.substr(0, dotPos) + text.substr(dotPos + 1); std::string digits = text.substr(0, dotPos) + text.substr(dotPos + 1);
unscaledValue_ = BigInteger(digits); m_unscaledValue = BigInteger(digits);
} else { } else {
scale_ = 0; m_scale = 0;
unscaledValue_ = BigInteger(text); m_unscaledValue = BigInteger(text);
} }
} }
@@ -59,26 +59,26 @@ BigDecimal::BigDecimal(const char* value)
: BigDecimal(value == nullptr ? std::string("0") : std::string(value)) {} : BigDecimal(value == nullptr ? std::string("0") : std::string(value)) {}
BigDecimal::BigDecimal(const BigInteger& unscaledValue, int scale) BigDecimal::BigDecimal(const BigInteger& unscaledValue, int scale)
: unscaledValue_(unscaledValue), scale_(scale) { : m_unscaledValue(unscaledValue), m_scale(scale) {
if (scale < 0) { if (scale < 0) {
throw std::invalid_argument("scale cannot be negative"); throw std::invalid_argument("scale cannot be negative");
} }
} }
bool BigDecimal::isZero() const { bool BigDecimal::isZero() const {
return unscaledValue_.isZero(); return m_unscaledValue.isZero();
} }
int BigDecimal::sign() const { int BigDecimal::sign() const {
return unscaledValue_.sign(); return m_unscaledValue.sign();
} }
int BigDecimal::getScale() const { int BigDecimal::getScale() const {
return scale_; return m_scale;
} }
BigInteger BigDecimal::getUnscaledValue() const { BigInteger BigDecimal::getUnscaledValue() const {
return unscaledValue_; return m_unscaledValue;
} }
std::string BigDecimal::toString() const { std::string BigDecimal::toString() const {
@@ -86,7 +86,7 @@ std::string BigDecimal::toString() const {
return "0"; return "0";
} }
std::string digitStr = unscaledValue_.toString(); std::string digitStr = m_unscaledValue.toString();
// 处理符号 // 处理符号
bool negative = false; bool negative = false;
@@ -96,26 +96,26 @@ std::string BigDecimal::toString() const {
} }
// 插入小数点 // 插入小数点
if (scale_ == 0) { if (m_scale == 0) {
return (negative ? "-" : "") + digitStr; return (negative ? "-" : "") + digitStr;
} }
if (static_cast<int>(digitStr.size()) <= scale_) { if (static_cast<int>(digitStr.size()) <= m_scale) {
// 需要前置 "0." // 需要前置 "0."
std::string result = "0."; std::string result = "0.";
for (int i = 0; i < scale_ - static_cast<int>(digitStr.size()); i++) { for (int i = 0; i < m_scale - static_cast<int>(digitStr.size()); i++) {
result += "0"; result += "0";
} }
result += digitStr; result += digitStr;
return (negative ? "-" : "") + result; return (negative ? "-" : "") + result;
} }
int dotPos = digitStr.size() - scale_; int dotPos = static_cast<int>(digitStr.size()) - m_scale;
std::string result = digitStr.substr(0, dotPos) + "." + digitStr.substr(dotPos); std::string result = digitStr.substr(0, dotPos) + "." + digitStr.substr(dotPos);
return (negative ? "-" : "") + result; return (negative ? "-" : "") + result;
} }
void BigDecimal::alignScale(BigInteger& lhs, int& lhsScale, void BigDecimal::m_alignScale(BigInteger& lhs, int& lhsScale,
BigInteger& rhs, int& rhsScale) { BigInteger& rhs, int& rhsScale) {
if (lhsScale < rhsScale) { if (lhsScale < rhsScale) {
// 左边需要扩大 // 左边需要扩大
@@ -134,11 +134,11 @@ void BigDecimal::alignScale(BigInteger& lhs, int& lhsScale,
bool BigDecimal::operator==(const BigDecimal& other) const { bool BigDecimal::operator==(const BigDecimal& other) const {
if (isZero() && other.isZero()) return true; if (isZero() && other.isZero()) return true;
BigInteger lhs = unscaledValue_; BigInteger lhs = m_unscaledValue;
BigInteger rhs = other.unscaledValue_; BigInteger rhs = other.m_unscaledValue;
int lhsScale = scale_; int lhsScale = m_scale;
int rhsScale = other.scale_; int rhsScale = other.m_scale;
alignScale(lhs, lhsScale, rhs, rhsScale); m_alignScale(lhs, lhsScale, rhs, rhsScale);
return lhs == rhs; return lhs == rhs;
} }
@@ -147,17 +147,17 @@ bool BigDecimal::operator!=(const BigDecimal& other) const {
} }
bool BigDecimal::operator<(const BigDecimal& other) const { bool BigDecimal::operator<(const BigDecimal& other) const {
if (unscaledValue_.sign() != other.unscaledValue_.sign()) { if (m_unscaledValue.sign() != other.m_unscaledValue.sign()) {
return unscaledValue_.sign() < other.unscaledValue_.sign(); return m_unscaledValue.sign() < other.m_unscaledValue.sign();
} }
BigInteger lhs = unscaledValue_; BigInteger lhs = m_unscaledValue;
BigInteger rhs = other.unscaledValue_; BigInteger rhs = other.m_unscaledValue;
int lhsScale = scale_; int lhsScale = m_scale;
int rhsScale = other.scale_; int rhsScale = other.m_scale;
alignScale(lhs, lhsScale, rhs, rhsScale); m_alignScale(lhs, lhsScale, rhs, rhsScale);
if (unscaledValue_.sign() >= 0) { if (m_unscaledValue.sign() >= 0) {
return lhs < rhs; return lhs < rhs;
} else { } else {
return lhs > rhs; return lhs > rhs;
@@ -230,9 +230,9 @@ BigDecimal BigDecimal::operator+() const {
BigDecimal BigDecimal::operator-() const { BigDecimal BigDecimal::operator-() const {
if (isZero()) { if (isZero()) {
return BigDecimal(0); return {0};
} }
return BigDecimal(-unscaledValue_, scale_); return {-m_unscaledValue, m_scale};
} }
BigDecimal& BigDecimal::operator+=(const BigDecimal& other) { BigDecimal& BigDecimal::operator+=(const BigDecimal& other) {
@@ -259,13 +259,13 @@ BigDecimal BigDecimal::operator+(const BigDecimal& other) const {
if (isZero()) return other; if (isZero()) return other;
if (other.isZero()) return *this; if (other.isZero()) return *this;
BigInteger lhs = unscaledValue_; BigInteger lhs = m_unscaledValue;
BigInteger rhs = other.unscaledValue_; BigInteger rhs = other.m_unscaledValue;
int lhsScale = scale_; int lhsScale = m_scale;
int rhsScale = other.scale_; int rhsScale = other.m_scale;
alignScale(lhs, lhsScale, rhs, rhsScale); m_alignScale(lhs, lhsScale, rhs, rhsScale);
return BigDecimal(lhs + rhs, lhsScale); return {lhs + rhs, lhsScale};
} }
BigDecimal BigDecimal::operator-(const BigDecimal& other) const { BigDecimal BigDecimal::operator-(const BigDecimal& other) const {
@@ -274,13 +274,13 @@ BigDecimal BigDecimal::operator-(const BigDecimal& other) const {
BigDecimal BigDecimal::operator*(const BigDecimal& other) const { BigDecimal BigDecimal::operator*(const BigDecimal& other) const {
if (isZero() || other.isZero()) { if (isZero() || other.isZero()) {
return BigDecimal(0); return {0};
} }
BigInteger result = unscaledValue_ * other.unscaledValue_; BigInteger result = m_unscaledValue * other.m_unscaledValue;
int resultScale = scale_ + other.scale_; int resultScale = m_scale + other.m_scale;
return BigDecimal(result, resultScale); return {result, resultScale};
} }
BigDecimal BigDecimal::operator/(const BigDecimal& other) const { BigDecimal BigDecimal::operator/(const BigDecimal& other) const {
@@ -289,14 +289,14 @@ BigDecimal BigDecimal::operator/(const BigDecimal& other) const {
} }
if (isZero()) { if (isZero()) {
return BigDecimal(0); return {0};
} }
// 先对齐 scale,然后做整数除法 // 先对齐 scale,然后做整数除法
BigInteger lhs = unscaledValue_; BigInteger lhs = m_unscaledValue;
BigInteger rhs = other.unscaledValue_; BigInteger rhs = other.m_unscaledValue;
int lhsScale = scale_; int lhsScale = m_scale;
int rhsScale = other.scale_; int rhsScale = other.m_scale;
// 使用更高的精度进行除法 // 使用更高的精度进行除法
// 乘以 10^precision 来获得更多的精度 // 乘以 10^precision 来获得更多的精度
@@ -308,14 +308,14 @@ BigDecimal BigDecimal::operator/(const BigDecimal& other) const {
BigInteger quotient = lhs / rhs; BigInteger quotient = lhs / rhs;
int resultScale = lhsScale - rhsScale + precision; int resultScale = lhsScale - rhsScale + precision;
return BigDecimal(quotient, resultScale); return {quotient, resultScale};
} }
BigDecimal BigDecimal::abs() const { BigDecimal BigDecimal::abs() const {
if (unscaledValue_.sign() >= 0) { if (m_unscaledValue.sign() >= 0) {
return *this; return *this;
} }
return BigDecimal(-unscaledValue_, scale_); return {-m_unscaledValue, m_scale};
} }
BigDecimal BigDecimal::round(int scale) const { BigDecimal BigDecimal::round(int scale) const {
@@ -323,19 +323,19 @@ BigDecimal BigDecimal::round(int scale) const {
throw std::invalid_argument("scale cannot be negative"); throw std::invalid_argument("scale cannot be negative");
} }
if (scale >= scale_) { if (scale >= m_scale) {
return *this; return *this;
} }
// 简单实现:直接截断到指定小数位数 // 简单实现:直接截断到指定小数位数
int diff = scale_ - scale; int diff = m_scale - scale;
BigInteger divisor = BigInteger(10); BigInteger divisor = BigInteger(10);
for (int i = 1; i < diff; i++) { for (int i = 1; i < diff; i++) {
divisor = divisor * BigInteger(10); divisor = divisor * BigInteger(10);
} }
BigInteger rounded = unscaledValue_ / divisor; BigInteger rounded = m_unscaledValue / divisor;
return BigDecimal(rounded, scale); return {rounded, scale};
} }
std::ostream& operator<<(std::ostream& os, const BigDecimal& bd) { std::ostream& operator<<(std::ostream& os, const BigDecimal& bd) {
+211 -153
View File
@@ -7,52 +7,81 @@
namespace bstl { namespace bstl {
std::string BigInteger::trimLeadingZeros(const std::string& value) { namespace {
size_t pos = 0; std::vector<int> toDigits(unsigned long long value) {
while (pos < value.size() - 1 && value[pos] == '0') { std::vector<int> digits;
pos++; while (value > 0) {
digits.push_back(static_cast<int>(value % 10));
value /= 10;
} }
return value.substr(pos); return digits;
} }
} // namespace
int BigInteger::compareAbs(const std::string& a, const std::string& b) { std::vector<int> BigInteger::m_trimLeadingZeros(const std::vector<int>& value) {
std::string ta = trimLeadingZeros(a); size_t end = value.size();
std::string tb = trimLeadingZeros(b); while (end > 0 && value[end - 1] == 0) {
if (ta.size() != tb.size()) { --end;
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<int>(a.size()) - 1;
int j = static_cast<int>(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;
} }
std::vector<int> result(value);
result.resize(end);
return result; return result;
} }
std::string BigInteger::subAbs(const std::string& a, const std::string& b) { int BigInteger::m_compareAbs(const std::vector<int>& a, const std::vector<int>& b) {
std::string ta = trimLeadingZeros(a); std::vector<int> ta = m_trimLeadingZeros(a);
std::string tb = trimLeadingZeros(b); std::vector<int> tb = m_trimLeadingZeros(b);
if (compareAbs(ta, tb) < 0) { if (ta.size() != tb.size()) {
return subAbs(tb, ta); return ta.size() < tb.size() ? -1 : 1;
} }
std::string result; for (size_t i = ta.size(); i > 0; --i) {
if (ta[i - 1] != tb[i - 1]) {
return ta[i - 1] < tb[i - 1] ? -1 : 1;
}
}
return 0;
}
std::vector<int> BigInteger::m_addAbs(const std::vector<int>& a, const std::vector<int>& b) {
std::vector<int> ta = m_trimLeadingZeros(a);
std::vector<int> tb = m_trimLeadingZeros(b);
std::vector<int> result;
result.reserve(std::max(ta.size(), tb.size()) + 1);
int carry = 0;
const size_t n = std::max(ta.size(), tb.size());
for (size_t i = 0; i < n; ++i) {
int sum = carry;
if (i < ta.size()) {
sum += ta[i];
}
if (i < tb.size()) {
sum += tb[i];
}
result.push_back(sum % 10);
carry = sum / 10;
}
if (carry != 0) {
result.push_back(carry);
}
return m_trimLeadingZeros(result);
}
std::vector<int> BigInteger::m_subAbs(const std::vector<int>& a, const std::vector<int>& b) {
std::vector<int> ta = m_trimLeadingZeros(a);
std::vector<int> tb = m_trimLeadingZeros(b);
if (m_compareAbs(ta, tb) < 0) {
return m_subAbs(tb, ta);
}
std::vector<int> result;
result.reserve(ta.size());
int borrow = 0; int borrow = 0;
int i = static_cast<int>(ta.size()) - 1; for (size_t i = 0; i < ta.size(); ++i) {
int j = static_cast<int>(tb.size()) - 1; int diff = ta[i] - borrow;
while (i >= 0) { if (i < tb.size()) {
int diff = (ta[i--] - '0') - borrow; diff -= tb[i];
if (j >= 0) {
diff -= (tb[j--] - '0');
} }
if (diff < 0) { if (diff < 0) {
diff += 10; diff += 10;
@@ -60,132 +89,122 @@ std::string BigInteger::subAbs(const std::string& a, const std::string& b) {
} else { } else {
borrow = 0; borrow = 0;
} }
result = char('0' + diff) + result; result.push_back(diff);
} }
return trimLeadingZeros(result); return m_trimLeadingZeros(result);
} }
std::string BigInteger::mulAbs(const std::string& a, const std::string& b) { std::vector<int> BigInteger::m_mulAbs(const std::vector<int>& a, const std::vector<int>& b) {
std::string ta = trimLeadingZeros(a); std::vector<int> ta = m_trimLeadingZeros(a);
std::string tb = trimLeadingZeros(b); std::vector<int> tb = m_trimLeadingZeros(b);
if (ta == "0" || tb == "0") return "0"; if (ta.empty() || tb.empty()) {
return {};
}
std::vector<int> product(ta.size() + tb.size(), 0); std::vector<int> product(ta.size() + tb.size(), 0);
for (size_t i = 0; i < ta.size(); i++) { for (size_t i = 0; i < ta.size(); ++i) {
for (size_t j = 0; j < tb.size(); j++) { 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] += ta[i] * tb[j];
product[i + j] += mul;
} }
} }
int carry = 0; int carry = 0;
for (size_t i = 0; i < product.size(); i++) { for (int& digit : product) {
int sum = product[i] + carry; const int sum = digit + carry;
product[i] = sum % 10; digit = sum % 10;
carry = sum / 10; carry = sum / 10;
} }
std::string result; return m_trimLeadingZeros(product);
for (int i = static_cast<int>(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::vector<int> BigInteger::m_divAbs(const std::vector<int>& a, const std::vector<int>& b) {
std::string tb = trimLeadingZeros(b); std::vector<int> tb = m_trimLeadingZeros(b);
if (tb == "0") { if (tb.empty()) {
throw std::invalid_argument("division by zero"); throw std::invalid_argument("division by zero");
} }
std::string ta = trimLeadingZeros(a);
if (compareAbs(ta, tb) < 0) { std::vector<int> ta = m_trimLeadingZeros(a);
return "0"; if (m_compareAbs(ta, tb) < 0) {
return {};
} }
std::string quotient; std::vector<int> quotientHigh;
std::string current; std::vector<int> current;
for (char digit : ta) { current.reserve(ta.size());
current += digit;
current = trimLeadingZeros(current); for (size_t i = ta.size(); i > 0; --i) {
current.insert(current.begin(), ta[i - 1]);
current = m_trimLeadingZeros(current);
int count = 0; int count = 0;
while (compareAbs(current, tb) >= 0) { while (m_compareAbs(current, tb) >= 0) {
current = subAbs(current, tb); current = m_subAbs(current, tb);
count++; ++count;
} }
quotient += char('0' + count); quotientHigh.push_back(count);
} }
return trimLeadingZeros(quotient);
std::reverse(quotientHigh.begin(), quotientHigh.end());
return m_trimLeadingZeros(quotientHigh);
} }
BigInteger::BigInteger() : digits_("0"), sign_(0) {} BigInteger::BigInteger() : m_sign(0) {}
BigInteger::BigInteger(int value) : digits_("0"), sign_(1) { BigInteger::BigInteger(int value) : m_sign(0) {
if (value == 0) { if (value == 0) {
digits_ = "0";
sign_ = 0;
return; return;
} }
auto v = static_cast<long long>(value);
if (v < 0) {
m_sign = -1;
v = -v;
} else {
m_sign = 1;
}
m_digits = toDigits(static_cast<unsigned long long>(v));
}
BigInteger::BigInteger(long long value) : m_sign(0) {
if (value == 0) {
return;
}
unsigned long long magnitude = 0;
if (value < 0) { if (value < 0) {
sign_ = -1; m_sign = -1;
value = -value; magnitude = static_cast<unsigned long long>(-(value + 1)) + 1ULL;
} } else {
digits_.clear(); m_sign = 1;
while (value > 0) { magnitude = static_cast<unsigned long long>(value);
digits_ = char('0' + value % 10) + digits_;
value /= 10;
} }
m_digits = toDigits(magnitude);
} }
BigInteger::BigInteger(long long value) : digits_("0"), sign_(1) { BigInteger::BigInteger(unsigned long long value) : m_sign(0) {
if (value == 0) { if (value == 0) {
digits_ = "0";
sign_ = 0;
return; return;
} }
if (value < 0) { m_sign = 1;
sign_ = -1; m_digits = toDigits(value);
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) { BigInteger::BigInteger(const std::string& value) : m_sign(0) {
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()) { if (value.empty()) {
digits_ = "0";
sign_ = 0;
return; return;
} }
std::string text = value; std::string text = value;
sign_ = 1; m_sign = 1;
if (text[0] == '-') { if (text[0] == '-') {
sign_ = -1; m_sign = -1;
text = text.substr(1); text = text.substr(1);
} else if (text[0] == '+') { } else if (text[0] == '+') {
text = text.substr(1); text = text.substr(1);
} }
if (text.empty()) { if (text.empty()) {
digits_ = "0"; m_sign = 0;
sign_ = 0;
return; return;
} }
@@ -195,9 +214,14 @@ BigInteger::BigInteger(const std::string& value) : digits_("0"), sign_(1) {
} }
} }
digits_ = trimLeadingZeros(text); m_digits.clear();
if (digits_ == "0") { m_digits.reserve(text.size());
sign_ = 0; for (auto it = text.rbegin(); it != text.rend(); ++it) {
m_digits.push_back(*it - '0');
}
m_digits = m_trimLeadingZeros(m_digits);
if (m_digits.empty()) {
m_sign = 0;
} }
} }
@@ -205,21 +229,34 @@ BigInteger::BigInteger(const char* value)
: BigInteger(value == nullptr ? std::string("0") : std::string(value)) {} : BigInteger(value == nullptr ? std::string("0") : std::string(value)) {}
bool BigInteger::isZero() const { bool BigInteger::isZero() const {
return sign_ == 0 || digits_ == "0"; return m_sign == 0;
} }
int BigInteger::sign() const { int BigInteger::sign() const {
return isZero() ? 0 : sign_; return m_sign;
} }
std::string BigInteger::toString() const { std::string BigInteger::toString() const {
if (isZero()) return "0"; if (isZero()) {
return (sign_ < 0 ? "-" : "") + digits_; return "0";
}
std::string result;
result.reserve(m_digits.size() + (m_sign < 0 ? 1U : 0U));
if (m_sign < 0) {
result.push_back('-');
}
for (auto it = m_digits.rbegin(); it != m_digits.rend(); ++it) {
result.push_back(static_cast<char>('0' + *it));
}
return result;
} }
bool BigInteger::operator==(const BigInteger& other) const { bool BigInteger::operator==(const BigInteger& other) const {
if (isZero() && other.isZero()) return true; if (isZero() && other.isZero()) {
return sign_ == other.sign_ && digits_ == other.digits_; return true;
}
return m_sign == other.m_sign && m_digits == other.m_digits;
} }
bool BigInteger::operator!=(const BigInteger& other) const { bool BigInteger::operator!=(const BigInteger& other) const {
@@ -227,10 +264,14 @@ bool BigInteger::operator!=(const BigInteger& other) const {
} }
bool BigInteger::operator<(const BigInteger& other) const { bool BigInteger::operator<(const BigInteger& other) const {
if (sign_ != other.sign_) return sign_ < other.sign_; if (m_sign != other.m_sign) {
if (sign_ == 0) return false; return m_sign < other.m_sign;
int cmp = compareAbs(digits_, other.digits_); }
return sign_ > 0 ? cmp < 0 : cmp > 0; if (m_sign == 0) {
return false;
}
const int cmp = m_compareAbs(m_digits, other.m_digits);
return m_sign > 0 ? cmp < 0 : cmp > 0;
} }
bool BigInteger::operator>(const BigInteger& other) const { bool BigInteger::operator>(const BigInteger& other) const {
@@ -298,9 +339,11 @@ BigInteger BigInteger::operator+() const {
} }
BigInteger BigInteger::operator-() const { BigInteger BigInteger::operator-() const {
if (isZero()) return BigInteger(0); if (isZero()) {
return {0};
}
BigInteger result(*this); BigInteger result(*this);
result.sign_ = -result.sign_; result.m_sign = -result.m_sign;
return result; return result;
} }
@@ -325,27 +368,33 @@ BigInteger& BigInteger::operator/=(const BigInteger& other) {
} }
BigInteger BigInteger::operator+(const BigInteger& other) const { BigInteger BigInteger::operator+(const BigInteger& other) const {
if (isZero()) return other; if (isZero()) {
if (other.isZero()) return *this; return other;
}
if (other.isZero()) {
return *this;
}
BigInteger result; BigInteger result;
if (sign_ == other.sign_) { if (m_sign == other.m_sign) {
result.digits_ = addAbs(digits_, other.digits_); result.m_digits = m_addAbs(m_digits, other.m_digits);
result.sign_ = sign_; result.m_sign = m_sign;
} else { } else {
int cmp = compareAbs(digits_, other.digits_); const int cmp = m_compareAbs(m_digits, other.m_digits);
if (cmp == 0) { if (cmp == 0) {
result.digits_ = "0"; result.m_digits.clear();
result.sign_ = 0; result.m_sign = 0;
} else if (cmp > 0) { } else if (cmp > 0) {
result.digits_ = subAbs(digits_, other.digits_); result.m_digits = m_subAbs(m_digits, other.m_digits);
result.sign_ = sign_; result.m_sign = m_sign;
} else { } else {
result.digits_ = subAbs(other.digits_, digits_); result.m_digits = m_subAbs(other.m_digits, m_digits);
result.sign_ = other.sign_; result.m_sign = other.m_sign;
} }
} }
if (result.digits_ == "0") result.sign_ = 0; if (result.m_digits.empty()) {
result.m_sign = 0;
}
return result; return result;
} }
@@ -354,11 +403,16 @@ BigInteger BigInteger::operator-(const BigInteger& other) const {
} }
BigInteger BigInteger::operator*(const BigInteger& other) const { BigInteger BigInteger::operator*(const BigInteger& other) const {
if (isZero() || other.isZero()) return BigInteger(0); if (isZero() || other.isZero()) {
return {0};
}
BigInteger result; BigInteger result;
result.digits_ = mulAbs(digits_, other.digits_); result.m_digits = m_mulAbs(m_digits, other.m_digits);
result.sign_ = (sign_ * other.sign_); result.m_sign = m_sign * other.m_sign;
if (result.digits_ == "0") result.sign_ = 0; if (result.m_digits.empty()) {
result.m_sign = 0;
}
return result; return result;
} }
@@ -366,11 +420,16 @@ BigInteger BigInteger::operator/(const BigInteger& other) const {
if (other.isZero()) { if (other.isZero()) {
throw std::invalid_argument("division by zero"); throw std::invalid_argument("division by zero");
} }
if (isZero()) return BigInteger(0); if (isZero()) {
return {0};
}
BigInteger result; BigInteger result;
result.digits_ = divAbs(digits_, other.digits_); result.m_digits = m_divAbs(m_digits, other.m_digits);
result.sign_ = (sign_ * other.sign_); result.m_sign = m_sign * other.m_sign;
if (result.digits_ == "0") result.sign_ = 0; if (result.m_digits.empty()) {
result.m_sign = 0;
}
return result; return result;
} }
@@ -385,5 +444,4 @@ std::istream& operator>>(std::istream& is, BigInteger& bi) {
return is; return is;
} }
} // namespace bstl } // namespace bstl
+100 -115
View File
@@ -2,54 +2,55 @@
#include <sstream> #include <sstream>
#include <stdexcept> #include <stdexcept>
#include <utility>
namespace bstl { namespace bstl {
String::String() : data_("") {} String::String() = default;
String::String(const std::string& str) : data_(str) {} String::String(std::string str) : m_data(std::move(str)) {}
String::String(const char* str) : data_(str == nullptr ? "" : str) {} String::String(const char* str) : m_data(str == nullptr ? "" : str) {}
std::string String::str() const { std::string String::str() const {
return data_; return m_data;
} }
const char* String::c_str() const { const char* String::c_str() const {
return data_.c_str(); return m_data.c_str();
} }
size_t String::length() const { size_t String::length() const {
return data_.length(); return m_data.length();
} }
size_t String::size() const { size_t String::size() const {
return data_.size(); return m_data.size();
} }
bool String::empty() const { bool String::empty() const {
return data_.empty(); return m_data.empty();
} }
char String::at(size_t pos) const { char String::at(size_t pos) const {
if (pos >= data_.size()) { if (pos >= m_data.size()) {
throw std::out_of_range("String::at: index out of range"); throw std::out_of_range("String::at: index out of range");
} }
return data_[pos]; return m_data[pos];
} }
char String::operator[](size_t pos) const { char String::operator[](size_t pos) const {
return data_[pos]; return m_data[pos];
} }
char& String::operator[](size_t pos) { char& String::operator[](size_t pos) {
return data_[pos]; return m_data[pos];
} }
std::vector<String> String::split(const String& delimiter) const { std::vector<String> String::split(const String& delimiter) const {
std::vector<String> result; std::vector<String> result;
if (data_.empty()) { if (m_data.empty()) {
return result; return result;
} }
@@ -61,25 +62,25 @@ std::vector<String> String::split(const String& delimiter) const {
size_t start = 0; size_t start = 0;
size_t pos = 0; size_t pos = 0;
while ((pos = data_.find(delimiter.data_, start)) != std::string::npos) { while ((pos = m_data.find(delimiter.m_data, start)) != std::string::npos) {
result.push_back(String(data_.substr(start, pos - start))); result.emplace_back(m_data.substr(start, pos - start));
start = pos + delimiter.size(); start = pos + delimiter.size();
} }
result.push_back(String(data_.substr(start))); result.emplace_back(m_data.substr(start));
return result; return result;
} }
String String::join(const std::vector<String>& parts, const String& delimiter) { String String::join(const std::vector<String>& parts, const String& delimiter) {
if (parts.empty()) { if (parts.empty()) {
return String(""); return {""};
} }
std::string result = parts[0].str(); std::string result = parts[0].str();
for (size_t i = 1; i < parts.size(); i++) { for (size_t i = 1; i < parts.size(); i++) {
result += delimiter.str() + parts[i].str(); result += delimiter.str() + parts[i].str();
} }
return String(result); return {result};
} }
String String::replace(const String& oldStr, const String& newStr, int count) const { String String::replace(const String& oldStr, const String& newStr, int count) const {
@@ -87,140 +88,124 @@ String String::replace(const String& oldStr, const String& newStr, int count) co
return *this; return *this;
} }
std::string result = data_; std::string result = m_data;
size_t pos = 0; size_t pos = 0;
int replaced = 0; int replaced = 0;
while ((pos = result.find(oldStr.data_, pos)) != std::string::npos && (count < 0 || replaced < count)) { while ((pos = result.find(oldStr.m_data, pos)) != std::string::npos && (count < 0 || replaced < count)) {
result.replace(pos, oldStr.size(), newStr.str()); result.replace(pos, oldStr.size(), newStr.str());
pos += newStr.size(); pos += newStr.size();
replaced++; replaced++;
} }
return String(result); return {result};
} }
String String::upper() const { String String::upper() const {
std::string result = data_; std::string result = m_data;
std::transform(result.begin(), result.end(), result.begin(), std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::toupper(c); }); [](unsigned char c) { return std::toupper(c); });
return String(result); return {result};
} }
String String::lower() const { String String::lower() const {
std::string result = data_; std::string result = m_data;
std::transform(result.begin(), result.end(), result.begin(), std::transform(result.begin(), result.end(), result.begin(),
[](unsigned char c) { return std::tolower(c); }); [](unsigned char c) { return std::tolower(c); });
return String(result); return {result};
} }
String String::capitalize() const { String String::capitalize() const {
if (data_.empty()) { if (m_data.empty()) {
return *this; return *this;
} }
std::string result = data_; std::string result = m_data;
result[0] = std::toupper(static_cast<unsigned char>(result[0])); result[0] = static_cast<char>(std::toupper(static_cast<unsigned char>(result[0])));
for (size_t i = 1; i < result.size(); i++) { for (size_t i = 1; i < result.size(); i++) {
result[i] = std::tolower(static_cast<unsigned char>(result[i])); result[i] = static_cast<char>(std::tolower(static_cast<unsigned char>(result[i])));
} }
return String(result); return {result};
} }
String String::title() const { String String::title() const {
std::string result = data_; std::string result = m_data;
bool newWord = true; bool newWord = true;
for (size_t i = 0; i < result.size(); i++) { for (char & i : result) {
if (std::isspace(static_cast<unsigned char>(result[i]))) { if (std::isspace(static_cast<unsigned char>(i))) {
newWord = true; newWord = true;
} else { } else {
if (newWord) { if (newWord) {
result[i] = std::toupper(static_cast<unsigned char>(result[i])); i = static_cast<char>(std::toupper(static_cast<unsigned char>(i)));
newWord = false; newWord = false;
} else { } else {
result[i] = std::tolower(static_cast<unsigned char>(result[i])); i = static_cast<char>(std::tolower(static_cast<unsigned char>(i)));
} }
} }
} }
return String(result); return {result};
} }
bool String::startswith(const String& prefix) const { bool String::startswith(const String& prefix) const {
if (prefix.size() > data_.size()) { if (prefix.size() > m_data.size()) {
return false; return false;
} }
return data_.compare(0, prefix.size(), prefix.data_) == 0; return m_data.compare(0, prefix.size(), prefix.m_data) == 0;
} }
bool String::endswith(const String& suffix) const { bool String::endswith(const String& suffix) const {
if (suffix.size() > data_.size()) { if (suffix.size() > m_data.size()) {
return false; return false;
} }
return data_.compare(data_.size() - suffix.size(), suffix.size(), suffix.data_) == 0; return m_data.compare(m_data.size() - suffix.size(), suffix.size(), suffix.m_data) == 0;
} }
bool String::contains(const String& substring) const { bool String::contains(const String& substring) const {
return data_.find(substring.data_) != std::string::npos; return m_data.find(substring.m_data) != std::string::npos;
} }
bool String::isdigit() const { bool String::isdigit() const {
if (data_.empty()) return false; return !m_data.empty() &&
for (unsigned char c : data_) { std::all_of(m_data.begin(), m_data.end(),
if (!std::isdigit(c)) return false; [](unsigned char c) { return std::isdigit(c) != 0; });
}
return true;
} }
bool String::isalpha() const { bool String::isalpha() const {
if (data_.empty()) return false; return !m_data.empty() &&
for (unsigned char c : data_) { std::all_of(m_data.begin(), m_data.end(),
if (!std::isalpha(c)) return false; [](unsigned char c) { return std::isalpha(c) != 0; });
}
return true;
} }
bool String::isalnum() const { bool String::isalnum() const {
if (data_.empty()) return false; return !m_data.empty() &&
for (unsigned char c : data_) { std::all_of(m_data.begin(), m_data.end(),
if (!std::isalnum(c)) return false; [](unsigned char c) { return std::isalnum(c) != 0; });
}
return true;
} }
bool String::isspace() const { bool String::isspace() const {
if (data_.empty()) return false; return !m_data.empty() &&
for (unsigned char c : data_) { std::all_of(m_data.begin(), m_data.end(),
if (!std::isspace(c)) return false; [](unsigned char c) { return std::isspace(c) != 0; });
}
return true;
} }
bool String::isupper() const { bool String::isupper() const {
if (data_.empty()) return false; return !m_data.empty() &&
for (unsigned char c : data_) { std::all_of(m_data.begin(), m_data.end(),
if (std::isalpha(c) && !std::isupper(c)) { [](unsigned char c) { return !std::isalpha(c) || std::isupper(c) != 0; });
return false;
}
}
return true;
} }
bool String::islower() const { bool String::islower() const {
if (data_.empty()) return false; return !m_data.empty() &&
for (unsigned char c : data_) { std::all_of(m_data.begin(), m_data.end(),
if (std::isalpha(c) && !std::islower(c)) { [](unsigned char c) { return !std::isalpha(c) || std::islower(c) != 0; });
return false;
}
}
return true;
} }
int String::find(const String& substring, size_t start) const { int String::find(const String& substring, size_t start) const {
size_t pos = data_.find(substring.data_, start); size_t pos = m_data.find(substring.m_data, start);
return pos == std::string::npos ? -1 : static_cast<int>(pos); return pos == std::string::npos ? -1 : static_cast<int>(pos);
} }
int String::rfind(const String& substring) const { int String::rfind(const String& substring) const {
size_t pos = data_.rfind(substring.data_); size_t pos = m_data.rfind(substring.m_data);
return pos == std::string::npos ? -1 : static_cast<int>(pos); return pos == std::string::npos ? -1 : static_cast<int>(pos);
} }
@@ -228,7 +213,7 @@ int String::count(const String& substring) const {
if (substring.empty()) return 0; if (substring.empty()) return 0;
int count = 0; int count = 0;
size_t pos = 0; size_t pos = 0;
while ((pos = data_.find(substring.data_, pos)) != std::string::npos) { while ((pos = m_data.find(substring.m_data, pos)) != std::string::npos) {
count++; count++;
pos += substring.size(); pos += substring.size();
} }
@@ -237,126 +222,126 @@ int String::count(const String& substring) const {
String String::strip() const { String String::strip() const {
size_t start = 0; size_t start = 0;
size_t end = data_.size(); size_t end = m_data.size();
while (start < end && std::isspace(static_cast<unsigned char>(data_[start]))) { while (start < end && std::isspace(static_cast<unsigned char>(m_data[start]))) {
start++; start++;
} }
while (end > start && std::isspace(static_cast<unsigned char>(data_[end - 1]))) { while (end > start && std::isspace(static_cast<unsigned char>(m_data[end - 1]))) {
end--; end--;
} }
return String(data_.substr(start, end - start)); return {m_data.substr(start, end - start)};
} }
String String::lstrip() const { String String::lstrip() const {
size_t start = 0; size_t start = 0;
while (start < data_.size() && std::isspace(static_cast<unsigned char>(data_[start]))) { while (start < m_data.size() && std::isspace(static_cast<unsigned char>(m_data[start]))) {
start++; start++;
} }
return String(data_.substr(start)); return {m_data.substr(start)};
} }
String String::rstrip() const { String String::rstrip() const {
size_t end = data_.size(); size_t end = m_data.size();
while (end > 0 && std::isspace(static_cast<unsigned char>(data_[end - 1]))) { while (end > 0 && std::isspace(static_cast<unsigned char>(m_data[end - 1]))) {
end--; end--;
} }
return String(data_.substr(0, end)); return {m_data.substr(0, end)};
} }
String String::strip(const String& chars) const { String String::strip(const String& chars) const {
size_t start = 0; size_t start = 0;
size_t end = data_.size(); size_t end = m_data.size();
while (start < end && chars.data_.find(data_[start]) != std::string::npos) { while (start < end && chars.m_data.find(m_data[start]) != std::string::npos) {
start++; start++;
} }
while (end > start && chars.data_.find(data_[end - 1]) != std::string::npos) { while (end > start && chars.m_data.find(m_data[end - 1]) != std::string::npos) {
end--; end--;
} }
return String(data_.substr(start, end - start)); return {m_data.substr(start, end - start)};
} }
String String::ljust(size_t width, char fillchar) const { String String::ljust(size_t width, char fillchar) const {
if (data_.size() >= width) { if (m_data.size() >= width) {
return *this; return *this;
} }
std::string result = data_; std::string result = m_data;
result.append(width - data_.size(), fillchar); result.append(width - m_data.size(), fillchar);
return String(result); return {result};
} }
String String::rjust(size_t width, char fillchar) const { String String::rjust(size_t width, char fillchar) const {
if (data_.size() >= width) { if (m_data.size() >= width) {
return *this; return *this;
} }
std::string result(width - data_.size(), fillchar); std::string result(width - m_data.size(), fillchar);
result.append(data_); result.append(m_data);
return String(result); return {result};
} }
String String::center(size_t width, char fillchar) const { String String::center(size_t width, char fillchar) const {
if (data_.size() >= width) { if (m_data.size() >= width) {
return *this; return *this;
} }
size_t totalPad = width - data_.size(); size_t totalPad = width - m_data.size();
size_t leftPad = totalPad / 2; size_t leftPad = totalPad / 2;
size_t rightPad = totalPad - leftPad; size_t rightPad = totalPad - leftPad;
std::string result(leftPad, fillchar); std::string result(leftPad, fillchar);
result.append(data_); result.append(m_data);
result.append(rightPad, fillchar); result.append(rightPad, fillchar);
return String(result); return {result};
} }
int String::toInt() const { int String::toInt() const {
return std::stoi(data_); return std::stoi(m_data);
} }
long long String::toLongLong() const { long long String::toLongLong() const {
return std::stoll(data_); return std::stoll(m_data);
} }
double String::toDouble() const { double String::toDouble() const {
return std::stod(data_); return std::stod(m_data);
} }
String String::operator+(const String& other) const { String String::operator+(const String& other) const {
return String(data_ + other.data_); return {m_data + other.m_data};
} }
String String::operator+(const char* str) const { String String::operator+(const char* str) const {
return String(data_ + (str == nullptr ? "" : str)); return {m_data + (str == nullptr ? "" : str)};
} }
String& String::operator+=(const String& other) { String& String::operator+=(const String& other) {
data_ += other.data_; m_data += other.m_data;
return *this; return *this;
} }
bool String::operator==(const String& other) const { bool String::operator==(const String& other) const {
return data_ == other.data_; return m_data == other.m_data;
} }
bool String::operator!=(const String& other) const { bool String::operator!=(const String& other) const {
return data_ != other.data_; return m_data != other.m_data;
} }
bool String::operator<(const String& other) const { bool String::operator<(const String& other) const {
return data_ < other.data_; return m_data < other.m_data;
} }
bool String::operator>(const String& other) const { bool String::operator>(const String& other) const {
return data_ > other.data_; return m_data > other.m_data;
} }
bool String::operator<=(const String& other) const { bool String::operator<=(const String& other) const {
return data_ <= other.data_; return m_data <= other.m_data;
} }
bool String::operator>=(const String& other) const { bool String::operator>=(const String& other) const {
return data_ >= other.data_; return m_data >= other.m_data;
} }
std::ostream& operator<<(std::ostream& os, const String& str) { std::ostream& operator<<(std::ostream& os, const String& str) {
+7 -7
View File
@@ -7,19 +7,19 @@
int main() { int main() {
using bstl::BigInteger; using bstl::BigInteger;
BigInteger a("12345678901234567890"); const BigInteger a("12345678901234567890");
BigInteger b("98765432109876543210"); const BigInteger b("98765432109876543210");
BigInteger c = a + b; const BigInteger c = a + b;
BigInteger d = b - a; const BigInteger d = b - a;
BigInteger e = a * BigInteger("2"); const BigInteger e = a * BigInteger("2");
BigInteger f = BigInteger("100000000000000000000000") / BigInteger("1000000000000000000"); const BigInteger f = BigInteger("100000000000000000000000") / BigInteger("1000000000000000000");
assert(c.toString() == "111111111011111111100"); assert(c.toString() == "111111111011111111100");
assert(d.toString() == "86419753208641975320"); assert(d.toString() == "86419753208641975320");
assert(e.toString() == "24691357802469135780"); assert(e.toString() == "24691357802469135780");
assert(f.toString() == "100000"); assert(f.toString() == "100000");
BigInteger zero("0"); const BigInteger zero("0");
assert((a == a) == true); assert((a == a) == true);
assert((a != b) == true); assert((a != b) == true);
assert((zero == 0) == true); assert((zero == 0) == true);