diff --git a/README.md b/README.md index 8cc5e2a..6a16835 100644 --- a/README.md +++ b/README.md @@ -37,17 +37,19 @@ This repository includes [TOMLMojo](https://github.com/forfudan/decimojo/tree/ma DeciMojo is available in the [modular-community](https://repo.prefix.dev/modular-community) package repository. You can install it using any of these methods: -From the `pixi` CLI, simply run ```pixi add decimojo```. This fetches the latest version and makes it immediately available for import. +1. From the `pixi` CLI, run the command ```pixi add decimojo```. This fetches the latest version and makes it immediately available for import. -For projects with a `mojoproject.toml`file, add the dependency: +1. In the `mojoproject.toml` file of your project, add the following dependency: -```toml -decimojo = "==0.5.0" -``` + ```toml + decimojo = "==0.5.0" + ``` + + Then run `pixi install` to download and install the package. -Then run `pixi install` to download and install the package. +1. For the latest development version in the `main` branch, clone [this GitHub repository](https://github.com/forfudan/decimojo) and build the package locally using the command `pixi run package`. -For the latest development version, clone the [GitHub repository](https://github.com/forfudan/decimojo) and build the package locally. +The following table summarizes the package versions and their corresponding Mojo versions: | `decimojo` | `mojo` | package manager | | ---------- | ------------- | --------------- | @@ -56,7 +58,7 @@ For the latest development version, clone the [GitHub repository](https://github | v0.3.0 | ==25.2 | magic | | v0.3.1 | >=25.2, <25.4 | pixi | | v0.4.x | ==25.4 | pixi | -| v0.5.0 | ==25.4 | pixi | +| v0.5.0 | ==25.5 | pixi | ## Quick start @@ -77,7 +79,7 @@ This will import the following types or aliases into your namespace: --- -Here are some examples showcasing the arbitrary-precision feature of the `BigDecimal` type (`BDec`). For some mathematical operations, the default precision (number of significant digits) is set to `36`. You can change the precision by passing the `precision` argument to the function. This default precision will be configurable globally in future when Mojo supports global variables. +Here are some examples showcasing the arbitrary-precision feature of the `BigDecimal` type (aliases: `BDec` and `Decimal`). For some mathematical operations, the default precision (number of significant digits) is set to `36`. You can change the precision by passing the `precision` argument to the function. This default precision will be configurable globally in future when Mojo supports global variables. ```mojo from decimojo.prelude import * @@ -186,7 +188,7 @@ fn main() raises: print(a.is_zero()) # Check for zero: False # === Type Conversions === - print(a.to_str()) # To string: "12345678901234567890" + print(String(a)) # To string: "12345678901234567890" # === Sign Handling === print(-a) # Negation: -12345678901234567890 diff --git a/docs/changelog.md b/docs/changelog.md index 304737d..393ca5d 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -2,9 +2,9 @@ This is a list of RELEASED changes for the DeciMojo Package. -## 20250801 (v0.5.0) +## 20250806 (v0.5.0) -DeciMojo v0.5.0 introduces significant enhancements to the `BigDecimal` and `BigUInt` types, including new mathematical functions and performance optimizations. The release adds **trigonometric functions** for `BigDecimal`, implements the **Chudnovsky algorithm** for computing π, implements the **Karatsuba multiplication algorithm** and **Burnikel-Ziegler fast division algorithm** for `BigUInt`. In-place subtraction is now supported for `BigUInt`, and SIMD is utilized for arithmetic operations. The `Decimal` type is renamed to `Decimal128` to reflect its 128-bit fixed precision. The release also includes improved error handling, optimized type conversions, and comprehensive documentation updates. +DeciMojo v0.5.0 introduces significant enhancements to the `BigDecimal` and `BigUInt` types, including new mathematical functions and performance optimizations. The release adds **trigonometric functions** for `BigDecimal`, implements the **Chudnovsky algorithm** for computing π, and implements the **Karatsuba multiplication algorithm** and **Burnikel-Ziegler division algorithm** for `BigUInt`. In-place operations, slice operations, and SIMD operations are now supported for `BigUInt` arithmetic. The `Decimal` type is renamed to `Decimal128` to reflect its 128-bit fixed precision. The release also includes improved error handling, optimized type conversions, refactored testing suites, and documentation updates. DeciMojo v0.5.0 is compatible with Mojo v25.5. diff --git a/docs/examples_on_bdec.mojo b/docs/examples_on_bigdecimal.mojo similarity index 100% rename from docs/examples_on_bdec.mojo rename to docs/examples_on_bigdecimal.mojo diff --git a/docs/examples_on_bigint.mojo b/docs/examples_on_bigint.mojo new file mode 100644 index 0000000..6a97e18 --- /dev/null +++ b/docs/examples_on_bigint.mojo @@ -0,0 +1,40 @@ +from decimojo.prelude import * + + +fn main() raises: + # === Construction === + var a = BigInt("12345678901234567890") # From string + var b = BInt(12345) # From integer + + # === Basic Arithmetic === + print(a + b) # Addition: 12345678901234580235 + print(a - b) # Subtraction: 12345678901234555545 + print(a * b) # Multiplication: 152415787814108380241050 + + # === Division Operations === + print(a // b) # Floor division: 999650944609516 + print(a.truncate_divide(b)) # Truncate division: 999650944609516 + print(a % b) # Modulo: 9615 + + # === Power Operation === + print(BInt(2).power(10)) # Power: 1024 + print(BInt(2) ** 10) # Power (using ** operator): 1024 + + # === Comparison === + print(a > b) # Greater than: True + print(a == BInt("12345678901234567890")) # Equality: True + print(a.is_zero()) # Check for zero: False + + # === Type Conversions === + print(String(a)) # To string: "12345678901234567890" + + # === Sign Handling === + print(-a) # Negation: -12345678901234567890 + print( + abs(BInt("-12345678901234567890")) + ) # Absolute value: 12345678901234567890 + print(a.is_negative()) # Check if negative: False + + # === Extremely large numbers === + # 3600 digits // 1800 digits + print(BInt("123456789" * 400) // BInt("987654321" * 200)) diff --git a/docs/examples_on_decimal128.mojo b/docs/examples_on_decimal128.mojo new file mode 100644 index 0000000..4fedcc3 --- /dev/null +++ b/docs/examples_on_decimal128.mojo @@ -0,0 +1,61 @@ +from decimojo.prelude import * + + +fn main() raises: + # === Construction === + var a = Dec128("123.45") # From string + var b = Dec128(123) # From integer + var c = Dec128(123, 2) # Integer with scale (1.23) + var d = Dec128.from_float(3.14159) # From floating-point + + # === Basic Arithmetic === + print(a + b) # Addition: 246.45 + print(a - b) # Subtraction: 0.45 + print(a * b) # Multiplication: 15184.35 + print(a / b) # Division: 1.0036585365853658536585365854 + + # === Rounding & Precision === + print(a.round(1)) # Round to 1 decimal place: 123.5 + print(a.quantize(Dec128("0.01"))) # Format to 2 decimal places: 123.45 + print(a.round(0, RoundingMode.ROUND_DOWN)) # Round down to integer: 123 + + # === Comparison === + print(a > b) # Greater than: True + print(a == Dec128("123.45")) # Equality: True + print(a.is_zero()) # Check for zero: False + print(Dec128("0").is_zero()) # Check for zero: True + + # === Type Conversions === + print(Float64(a)) # To float: 123.45 + print(a.to_int()) # To integer: 123 + print(a.to_str()) # To string: "123.45" + print(a.coefficient()) # Get coefficient: 12345 + print(a.scale()) # Get scale: 2 + + # === Mathematical Functions === + print(Dec128("2").sqrt()) # Square root: 1.4142135623730950488016887242 + print(Dec128("100").root(3)) # Cube root: 4.641588833612778892410076351 + print(Dec128("2.71828").ln()) # Natural log: 0.9999993273472820031578910056 + print(Dec128("10").log10()) # Base-10 log: 1 + print( + Dec128("16").log(Dec128("2")) + ) # Log base 2: 3.9999999999999999999999999999 + print(Dec128("10").exp()) # e^10: 22026.465794806716516957900645 + print(Dec128("2").power(10)) # Power: 1024 + + # === Sign Handling === + print(-a) # Negation: -123.45 + print(abs(Dec128("-123.45"))) # Absolute value: 123.45 + print(Dec128("123.45").is_negative()) # Check if negative: False + + # === Special Values === + print(Dec128.PI()) # π constant: 3.1415926535897932384626433833 + print(Dec128.E()) # e constant: 2.7182818284590452353602874714 + print(Dec128.ONE()) # Value 1: 1 + print(Dec128.ZERO()) # Value 0: 0 + print(Dec128.MAX()) # Maximum value: 79228162514264337593543950335 + + # === Convenience Methods === + print(Dec128("123.400").is_integer()) # Check if integer: False + print(a.number_of_significant_digits()) # Count significant digits: 5 + print(Dec128("12.34").to_str_scientific()) # Scientific notation: 1.234E+1 diff --git a/docs/readme_zht.md b/docs/readme_zht.md index e48bfc0..29eea33 100644 --- a/docs/readme_zht.md +++ b/docs/readme_zht.md @@ -1,36 +1,268 @@ -# DeciMojo +# DeciMojo -由 [Mojo 程序設計語言 🔥](https://www.modular.com/mojo) 實現的定點數和整數運算庫。 +由 [Mojo 程序設計語言 🔥](https://www.modular.com/mojo) 實現的任意精度小數和整數運算庫。 -**[GitHub 倉庫»](https://github.com/forfudan/decimojo)** +**[English](https://zhuyuhao.com/decimojo/)** | **[更新日誌](https://zhuyuhao.com/decimojo/docs/changelog.html)** | **[GitHub 倉庫»](https://github.com/forfudan/decimojo)** | **[Discord 頻道»](https://discord.gg/3rGH87uZTk)** + +- [概述](#概述) +- [安裝](#安裝) +- [快速開始](#快速開始) +- [目標](#目標) +- [命名](#命名) +- [狀態](#狀態) +- [測試與基準](#測試與基準) +- [引用](#引用) +- [許可證](#許可證) ## 概述 -DeciMojo 爲 Mojo 提供了全面的定點數和整數運算庫,專爲處理金融計算、工程計算、以及其他需要避免浮點數捨入誤差的場景而設計。 +DeciMojo 爲 Mojo 提供任意精度小數和整數運算庫,爲金融建模、科學計算以及浮點近似誤差不可接受的應用提供精確計算。除了基本算術運算外,該庫還包括具有保證精度的高級數學函數。 核心類型包括: -- 128 位定點數 (`Decimal128`),支持最多 29 位有效數字,小數點後最多 28 位數字[^fixed]。 -- 任意精度定點數 (`BigDecimal`) ,允許進行無限位數和小數位的計算。 -- 基於 10 進制的任意精度有符號整數 (`BigInt`) 和任意精度無符號整數 (`BigUInt`)[^integer],支持無限位數。它具有全面的算術運算、比較功能,並能高效支持超大整數計算。 +- 基於 10 進制的任意精度有符號整數類型 (`BigInt`) 和任意精度無符號整數類型 (`BigUInt`),支持無限位數[^integer]。它具有全面的算術運算、比較功能,並能高效支持超大整數計算。 +- 任意精度小數實現 (`BigDecimal`),允許進行無限位數和小數位的計算[^arbitrary]。它提供完整的算術運算、比較以及數學函數集合,如對數、指數、根、三角函數等。它還支持捨入模式以及與內建類型的轉換。 +- 128 位定點小數實現 (`Decimal128`),支持最多 29 位有效數字,小數點後最多 28 位數字[^fixed]。它具有完整的數學函數集合,包括對數、指數、根等。 + +此倉庫包含 [TOMLMojo](https://github.com/forfudan/decimojo/tree/main/src/tomlmojo),一個純 Mojo 實現的輕量級 TOML 解析器。它解析配置文件和測試數據,支持基本類型、數組和嵌套表。雖然爲 DeciMojo 的測試框架而創建,但它提供通用的結構化數據解析,具有簡潔的 API。 + +| 類型 | 別名 | 信息 | 內部表示 | +| ------------ | ----------------- | ------------------ | ----------------------------------- | +| `BigUInt` | `BUInt` | 任意精度無符號整數 | `List[UInt32]` | +| `BigInt` | `BInt` | 任意精度整數 | `BigUInt`, `Bool` | +| `BigDecimal` | `BDec`, `Decimal` | 任意精度小數 | `BigUInt`, `Int`, `Bool` | +| `Decimal128` | `Dec128` | 128 位定點精度小數 | `UInt32`,`UInt32`,`UInt32`,`UInt32` | ## 安裝 DeciMojo 可在 [modular-community](https://repo.prefix.dev/modular-community) 包倉庫中獲取。您可以使用以下任一方法進行安裝: -從 `pixi` CLI,只需運行 ```pixi add decimojo```。這會獲取最新版本並使其立即可用於導入。 +1. 從 `pixi` CLI,運行命令 ```pixi add decimojo```。這會獲取最新版本並使其立即可用於導入。 + +1. 在您項目的 `mojoproject.toml` 文件中,添加以下依賴: + + ```toml + decimojo = "==0.5.0" + ``` + + 然後運行 `pixi install` 來下載並安裝包。 + +1. 對於 `main` 分支中的最新開發版本,請克隆 [此 GitHub 倉庫](https://github.com/forfudan/decimojo) 並使用命令 `pixi run package` 在本地構建包。 + +下表總結了包版本及其對應的 Mojo 版本: + +| `decimojo` | `mojo` | 包管理器 | +| ---------- | ------------- | -------- | +| v0.1.0 | ==25.1 | magic | +| v0.2.0 | ==25.2 | magic | +| v0.3.0 | ==25.2 | magic | +| v0.3.1 | >=25.2, <25.4 | pixi | +| v0.4.x | ==25.4 | pixi | +| v0.5.0 | ==25.5 | pixi | -對於帶有 `mojoproject.toml` 文件的項目,添加依賴 ```decimojo = "==0.4.1"```。然後運行 `pixi install` 來下載並安裝包。 +## 快速開始 -如需最新的開發版本,請克隆 [GitHub 倉庫](https://github.com/forfudan/decimojo) 並在本地構建包。 +您可以通過導入 `decimojo` 模塊開始使用 DeciMojo。一個簡單的方法是從 `prelude` 模塊導入所有內容,它提供最常用的類型。 -| `decimojo` | `mojo` | 包管理 | -| ---------- | ------------- | ------ | -| v0.1.0 | >=25.1 | magic | -| v0.2.0 | >=25.2 | magic | -| v0.3.0 | >=25.2 | magic | -| v0.3.1 | >=25.2, <25.4 | pixi | -| v0.4.x | ==25.4 | pixi | +```mojo +from decimojo import * +``` + +這將導入以下類型或別名到您的命名空間: + +- `dm`: `decimojo` 模塊的別名。 +- `BigInt`(別名 `BInt`):任意精度有符號整數類型。 +- `BigDecimal`(別名 `BDec` 和 `Decimal`):任意精度小數類型。 +- `Decimal128`(別名 `Dec128`):128 位定點精度小數類型。 +- `RoundingMode`(別名 `RM`):捨入模式的枚舉。 +- `ROUND_DOWN`、`ROUND_HALF_UP`、`ROUND_HALF_EVEN`、`ROUND_UP`:常用捨入模式的常量。 + +--- + +以下是一些展示 `BigDecimal` 類型(別名:`BDec` 和 `Decimal`)任意精度特性的例子。對於某些數學運算,默認精度(有效數字位數)設為 `36`。您可以通過向函數傳遞 `precision` 參數來更改精度。當 Mojo 支持全局變量時,此默認精度將可以全局配置。 + +```mojo +from decimojo.prelude import * + + +fn main() raises: + var a = BDec("123456789.123456789") # BDec 是 BigDecimal 的別名 + var b = Decimal( + "1234.56789" + ) # Decimal 是類似 Python 的 BigDecimal 別名 + + # === 基本算術 === # + print(a + b) # 123458023.691346789 + print(a - b) # 123455554.555566789 + print(a * b) # 152415787654.32099750190521 + print(a.true_divide(b + 1)) # 99919.0656560820700835791386582569736 + + # === 指數函數 === # + print(a.sqrt(precision=80)) + # 11111.111066111110969430554981749302328338130654689094538188579359566416821203641 + print(a.cbrt(precision=80)) + # 497.93385938415242742001134219007635925452951248903093962731782327785111102410518 + print(a.root(b, precision=80)) + # 1.0152058862996527138602610522640944903320735973237537866713119992581006582644107 + print(a.power(b, precision=80)) + # 3.3463611024190802340238135400789468682196324482030786573104956727660098625641520E+9989 + print(a.exp(precision=80)) + # 1.8612755889649587035842377856492201091251654136588338983610243887893287518637652E+53616602 + print(a.log(b, precision=80)) + # 2.6173300266565482999078843564152939771708486260101032293924082259819624360226238 + print(a.ln(precision=80)) + # 18.631401767168018032693933348296537542797015174553735308351756611901741276655161 + + # === 三角函數 === # + print(a.sin(precision=200)) + # 0.99985093087193092464780008002600992896256609588456 + # 91036188395766389946401881352599352354527727927177 + # 79589259132243649550891532070326452232864052771477 + # 31418817041042336608522984511928095747763538486886 + print(b.cos(precision=1000)) + # -0.9969577603867772005841841569997528013669868536239849713029893885930748434064450375775817720425329394 + # 9756020177557431933434791661179643984869397089102223199519409695771607230176923201147218218258755323 + # 7563476302904118661729889931783126826250691820526961290122532541861737355873869924820906724540889765 + # 5940445990824482174517106016800118438405307801022739336016834311018727787337447844118359555063575166 + # 5092352912854884589824773945355279792977596081915868398143592738704592059567683083454055626123436523 + # 6998108941189617922049864138929932713499431655377552668020889456390832876383147018828166124313166286 + # 6004871998201597316078894718748251490628361253685772937806895692619597915005978762245497623003811386 + # 0913693867838452088431084666963414694032898497700907783878500297536425463212578556546527017688874265 + # 0785862902484462361413598747384083001036443681873292719322642381945064144026145428927304407689433744 + # 5821277763016669042385158254006302666602333649775547203560187716156055524418512492782302125286330865 + + # === 數字的內部表示 === # + ( + Decimal( + ).power(2, precision=60) + ).print_internal_representation() + # Internal Representation Details of BigDecimal + # ---------------------------------------------- + # number: 9.8696044010893586188344909998 + # 761511353136994072407906264133 + # 5 + # coefficient: 986960440108935861883449099987 + # 615113531369940724079062641335 + # negative: False + # scale: 59 + # word 0: 62641335 + # word 1: 940724079 + # word 2: 113531369 + # word 3: 99987615 + # word 4: 861883449 + # word 5: 440108935 + # word 6: 986960 + # ---------------------------------------------- +``` + +--- + +以下是展示 `BigInt` 類型(`BInt`)每個主要功能的綜合快速入門指南。 + +```mojo +from decimojo.prelude import * + +fn main() raises: + # === 構造 === + var a = BigInt("12345678901234567890") # 從字符串 + var b = BInt(12345) # 從整數 + + # === 基本算術 === + print(a + b) # 加法: 12345678901234580235 + print(a - b) # 減法: 12345678901234555545 + print(a * b) # 乘法: 152415787814108380241050 + + # === 除法運算 === + print(a // b) # 向下整除: 999650944609516 + print(a.truncate_divide(b)) # 截斷除法: 999650944609516 + print(a % b) # 取模: 9615 + + # === 冪運算 === + print(BInt(2).power(10)) # 冪: 1024 + print(BInt(2) ** 10) # 冪(使用 ** 運算符): 1024 + + # === 比較 === + print(a > b) # 大於: True + print(a == BInt("12345678901234567890")) # 相等: True + print(a.is_zero()) # 檢查是否爲零: False + + # === 類型轉換 === + print(String(a)) # 轉換爲字符串: "12345678901234567890" + + # === 符號處理 === + print(-a) # 取負: -12345678901234567890 + print(abs(BInt("-12345678901234567890"))) # 絕對值: 12345678901234567890 + print(a.is_negative()) # 檢查是否爲負: False + + # === 超大數字 === + # 3600 位數 // 1800 位數 + print(BInt("123456789" * 400) // BInt("987654321" * 200)) +``` + +--- + +以下是展示 `Decimal128` 類型(`Dec128`)每個主要功能的綜合快速入門指南。 + +```mojo +from decimojo.prelude import * + +fn main() raises: + # === 構造 === + var a = Dec128("123.45") # 從字符串 + var b = Dec128(123) # 從整數 + var c = Dec128(123, 2) # 帶精度的整數 (1.23) + var d = Dec128.from_float(3.14159) # 從浮點數 + + # === 基本算術 === + print(a + b) # 加法: 246.45 + print(a - b) # 減法: 0.45 + print(a * b) # 乘法: 15184.35 + print(a / b) # 除法: 1.0036585365853658536585365854 + + # === 捨入與精度 === + print(a.round(1)) # 捨入到 1 位小數: 123.5 + print(a.quantize(Dec128("0.01"))) # 格式化到 2 位小數: 123.45 + print(a.round(0, RoundingMode.ROUND_DOWN)) # 向下捨入到整數: 123 + + # === 比較 === + print(a > b) # 大於: True + print(a == Dec128("123.45")) # 相等: True + print(a.is_zero()) # 檢查是否爲零: False + print(Dec128("0").is_zero()) # 檢查是否爲零: True + + # === 類型轉換 === + print(Float64(a)) # 轉換爲浮點數: 123.45 + print(a.to_int()) # 轉換爲整數: 123 + print(a.to_str()) # 轉換爲字符串: "123.45" + print(a.coefficient()) # 獲取係數: 12345 + print(a.scale()) # 獲取精度: 2 + + # === 數學函數 === + print(Dec128("2").sqrt()) # 平方根: 1.4142135623730950488016887242 + print(Dec128("100").root(3)) # 立方根: 4.641588833612778892410076351 + print(Dec128("2.71828").ln()) # 自然對數: 0.9999993273472820031578910056 + print(Dec128("10").log10()) # 以 10 爲底的對數: 1 + print(Dec128("16").log(Dec128("2"))) # 以 2 爲底的對數: 3.9999999999999999999999999999 + print(Dec128("10").exp()) # e^10: 22026.465794806716516957900645 + print(Dec128("2").power(10)) # 冪: 1024 + + # === 符號處理 === + print(-a) # 取負: -123.45 + print(abs(Dec128("-123.45"))) # 絕對值: 123.45 + print(Dec128("123.45").is_negative()) # 檢查是否爲負: False + + # === 特殊值 === + print(Dec128.PI()) # π 常數: 3.1415926535897932384626433833 + print(Dec128.E()) # e 常數: 2.7182818284590452353602874714 + print(Dec128.ONE()) # 值 1: 1 + print(Dec128.ZERO()) # 值 0: 0 + print(Dec128.MAX()) # 最大值: 79228162514264337593543950335 + + # === 便利方法 === + print(Dec128("123.400").is_integer()) # 檢查是否爲整數: False + print(a.number_of_significant_digits()) # 計算有效數字位數: 5 + print(Dec128("12.34").to_str_scientific()) # 科學計數法: 1.234E+1 +``` ## 目標 @@ -55,12 +287,14 @@ DeciMojo 結合了 "Deci" 和 "Mojo" 兩詞,反映了其目的和實現語言 羅馬不是一日建成的。DeciMojo 目前正在積極開發中。它已成功通過 **"讓它工作"** 階段,並已深入 **"讓它正確"** 階段,同時已實施多項優化。歡迎錯誤報告和功能請求!如果您遇到問題,請[在此提交](https://github.com/forfudan/decimojo/issues)。 +定期對比 Python 的 `decimal` 模塊的基準測試可在 `bench/` 文件夾中找到,記錄了性能優勢以及需要不同方法的少數特定操作。 + ## 測試與基準 在將倉庫克隆到本地磁盤後,您可以: -- 使用 `pixi run test`(或 `pixi run t`)運行測試。 -- 使用 `pixi run bench`(或 `pixi run b`)生成對比 `python.decimal` 模塊的基準測試日誌。日誌文件保存在 `benches/logs/` 中。 +- 使用 `pixi run test` 運行測試。 +- 使用 `pixi run bdec` 生成對比 `python.decimal` 模塊的基準測試日誌。日誌文件保存在 `benches/bigdecimal/logs/` 中。 ## 引用 @@ -70,9 +304,9 @@ DeciMojo 結合了 "Deci" 和 "Mojo" 兩詞,反映了其目的和實現語言 @software{Zhu.2025, author = {Zhu, Yuhao}, year = {2025}, - title = {DeciMojo: A fixed-point decimal arithmetic library in Mojo}, + title = {An arbitrary-precision decimal and integer mathematics library for Mojo}, url = {https://github.com/forfudan/decimojo}, - version = {0.4.1}, + version = {0.5.0}, note = {Computer Software} } ``` @@ -81,6 +315,6 @@ DeciMojo 結合了 "Deci" 和 "Mojo" 兩詞,反映了其目的和實現語言 本倉庫及其所有貢獻内容均採用 Apache 許可證 2.0 版本授權。 -[^fixed]: Decimal128 類型可以表示最多 29 位有效數字,小數點後最多 28 位數字的值。當數值超過最大可表示值(2^96 - 1)時,DeciMojo 會拋出錯誤或將數值捨入以符合這些約束。例如,8.8888888888888888888888888888(總共 29 個 8,小數點後 28 位)的有效數字超過了最大可表示值(2^96 - 1),會自動捨入爲 8.888888888888888888888888889(總共 28 個 8,小數點後 27 位)。DeciMojo 的 Decimal128 類型類似於 System.Decimal(C#/.NET)、Rust 中的 rust_decimal、SQL Server 中的 DECIMAL/NUMERIC 等。 - -[^integer]: BigInt 實現使用基於 10 的表示進行高效存儲和計算,支持對具有無限精度的整數進行操作。它提供了向下整除(向負無窮舍入)和截斷除法(向零舍入)語義,無論操作數符號如何,都能確保除法操作處理具有正確的數學行爲。 +[^fixed]: `Decimal128` 類型可以表示最多 29 位有效數字,小數點後最多 28 位數字的值。當數值超過最大可表示值(`2^96 - 1`)時,DeciMojo 會拋出錯誤或將數值捨入以符合這些約束。例如,`8.8888888888888888888888888888`(總共 29 個 8,小數點後 28 位)的有效數字超過了最大可表示值(`2^96 - 1`),會自動捨入爲 `8.888888888888888888888888889`(總共 28 個 8,小數點後 27 位)。DeciMojo 的 `Decimal128` 類型類似於 `System.Decimal`(C#/.NET)、Rust 中的 `rust_decimal`、SQL Server 中的 `DECIMAL/NUMERIC` 等。 +[^integer]: BigInt 實現對用戶使用基於 10 的表示(保持十進制語義),而內部使用優化的基於 10^9 的存儲系統進行高效計算。這種方法在人類可讀的十進制操作與高性能計算之間取得平衡。它提供向下整除(向負無窮舍入)和截斷除法(向零舍入)語義,無論操作數符號如何,都能確保除法操作具有正確的數學行爲。 +[^arbitrary]: 建立在我們已完成的 BigInt 實現之上,BigDecimal 將支持整數和小數部分的任意精度,類似於 Python 中的 `decimal` 和 `mpmath`、Java 中的 `java.math.BigDecimal` 等。 diff --git a/pixi.toml b/pixi.toml index 50ec81f..c5cb959 100644 --- a/pixi.toml +++ b/pixi.toml @@ -9,7 +9,7 @@ readme = "README.md" version = "0.5.0" [dependencies] -mojo = "*" +mojo = "==25.5" [tasks] # format the code diff --git a/src/decimojo/bigdecimal/constants.mojo b/src/decimojo/bigdecimal/constants.mojo index fd565a4..e3c2e15 100644 --- a/src/decimojo/bigdecimal/constants.mojo +++ b/src/decimojo/bigdecimal/constants.mojo @@ -155,25 +155,22 @@ alias PI_1024 = BigDecimal( # we check whether the precision is higher than the current precision. # If yes, then we save it into the global scope as cached value. fn pi(precision: Int) raises -> BigDecimal: - """Calculates π using the fastest available algorithm. - - - precision ≤ 1024: precomputed constant - - precision > 1024: Chudnovsky with binary splitting - """ + """Calculates π using the fastest available algorithm.""" if precision < 0: raise Error("Precision must be non-negative") - # Use precomputed value for precision ≤ 1024 - if precision <= 1024: - var result = PI_1024 - result.round_to_precision( - precision, - RoundingMode.ROUND_HALF_EVEN, - remove_extra_digit_due_to_rounding=True, - fill_zeros_to_precision=False, - ) - return result^ + # TODO: When global variables are supported, + # we can check if we have a cached value for the requested precision. + # if precision <= 1024: + # var result = PI_1024 + # result.round_to_precision( + # precision, + # RoundingMode.ROUND_HALF_EVEN, + # remove_extra_digit_due_to_rounding=True, + # fill_zeros_to_precision=False, + # ) + # return result^ # Use Chudnovsky with binary splitting for maximum speed return pi_chudnovsky_binary_split(precision) diff --git a/src/decimojo/biguint/arithmetics.mojo b/src/decimojo/biguint/arithmetics.mojo index eec2089..61a09d6 100644 --- a/src/decimojo/biguint/arithmetics.mojo +++ b/src/decimojo/biguint/arithmetics.mojo @@ -405,9 +405,7 @@ fn add_inplace_by_slice( ) # Copy the words from y return if y.is_zero_in_bounds(bounds=bounds_y): - debug_assert[assert_mode="none"]( - len(y.words) == 1, "add_inplace_by_slice(): leading zero words in y" - ) + # y slice is zero, which means that all the words in the slice are zero return var n_words_y_slice = bounds_y[1] - bounds_y[0] diff --git a/src/decimojo/biguint/exponential.mojo b/src/decimojo/biguint/exponential.mojo index 7aab595..e31cc69 100644 --- a/src/decimojo/biguint/exponential.mojo +++ b/src/decimojo/biguint/exponential.mojo @@ -94,6 +94,7 @@ fn sqrt(x: BigUInt) -> BigUInt: # Division by zero should not occur if guess is positive quotient = x.floor_divide(guess) except: + # This should not happen quotient = BigUInt.ONE guess += quotient