#big-decimal #decimal #incremental #big #decimal-number #game

break-eternity

一个数值库,可以表示从10^^1e308这样大的数到10^-(10^^1e308)这样小的数。

3个不稳定版本

0.2.0 2024年5月20日
0.1.1 2021年10月13日
0.1.0 2021年10月13日

#162 in 游戏开发

21 每月下载量

自定义许可

82KB
2K SLoC

break-eternity

https://crates.io/crates/break-eternity

Patashu的break_eternity.js的移植。

一个数值库,可以表示从10^^1e308这样大的数到10^-(10^^1e308)这样小的数。

这个库更注重速度而不是精度,旨在供游戏使用。

额外功能

此crate有2个额外功能可供使用

  • serde,增加了对serde的支持
  • godot,向派生特质添加了从gdnativeFromVariantToVariant

默认情况下,这两个功能都是禁用的。如果您想让这个库包含对其他库的支持,请提交一个issue并告诉我。我非常乐意添加更多对游戏引擎的支持,因为这个库是专为游戏设计的。

内部表示

十进制数的内部表示如下:Decimal::from_components(sign, layer, mag) == sign * 10^10^10^...(layer times) mag。因此,层0的数字就是 sign * mag,层1的数字是 sign * 10^mag,层2的数字是 sign * 10^10^mag,以此类推。

如果 layer > 0mag < 0.0,则数字的指数为负,例如 sign * 10^-10^10^10^ ... mag

  • sign 的值为 -1、0 或 1
  • layer 是一个非负整数
  • mag 是一个 f64,按照以下方式规范化:如果它大于 1e15,则对它取以 10 为底的对数并增加 layer。如果它小于 log10(9e15)(约 15.954)并且 layer > 0,则对它取 10 的幂并减少 layer。在 layer 为 0 时,从负的 mags 中提取符号。零(sign == 0 || (mag == 0.0 && layer == 0))在所有字段中变为 0, 0, 0

Decimal 实现了 CopyClone,因此可以安全地引用而不必担心。

创建 Decimal

您可以使用 Decimal::from_number(f64)Decimal::try_from(&str) 或手动使用 Decimal::from_components(sign, layer, mag)Decimal::from_mantissa_exponent(mantissa, exponent) 来创建 Decimal。

如果您使用结构体初始化语法,请确保运行 normalize() 函数以规范化 Decimal。

接受的字符串表示形式

M === M
eX === 10^X
MeX === M*10^X
eXeY === 10^(XeY)
MeXeY === M*10^(XeY)
eeX === 10^10^X
eeXeY === 10^10^(XeY)
eeeX === 10^10^10^X
eeeXeY === 10^10^10^(XeY)
eeee... (N es) X === 10^10^10^ ... (N 10^s) X
(e^N)X === 10^10^10^ ... (N 10^s) X
N PT X === 10^10^10^ ... (N 10^s) X
N PT (X) === 10^10^10^ ... (N 10^s) X
NpX === 10^10^10^ ... (N 10^s) X
X^Y === X^Y
X^^N === X^X^X^ ... (N X^s) 1
X^^N;Y === X^X^X^ ... (N X^s) Y
X^^^N === X^^X^^X^^ ... (N X^^s) 1
X^^^N;Y === X^^X^^X^^ ... (N X^^s) Y

操作

得益于Rust特质的强大功能,您可以使用常规运算符(+-*/%+=-=*=/=%=)进行数学运算,以及其他数学函数,例如:abs, neg, round, floor, ceil, trunc, recip, cmp, cmpabs, max, min, maxabs, minabs, log, log10, ln, pow, root, factorial, gamma, exp, sqrt, tetrate, iteratedexp, iteratedlog, layer_add_10, layer_add, slog, ssqrt, lambertw, pentate)。

相等性以特殊方式处理,如果两边的值都是NaN或无穷大,则它们相等。除此之外,十进制数字在1e-10的精度上被认为是相等的。

如上所示,模运算符也得到正确实现,应该与其他运算一样准确。

另一个简洁的特性是针对所有原始数字类型的运算符实现,这意味着您可以像这样进行加法操作:Decimal::from_number(1.0) + 2.0。转换也以相同的方式进行,任何原始数字类型都可以使用from()into()转换为十进制。

关于bug的注意事项

尽管我移植了这个库,但我对数学不太了解。事实上,我对如何正确应用像幂次方、超对数等东西毫无头绪。所以,如果您发现这些函数有任何问题,您可能需要向我解释我需要更改代码中的哪些部分。

我知道这并不太专业,但我缺乏时间去获得数学学位或进一步学习这个主题。这个crate几乎是出于必要性而诞生的,因为我想要在我的游戏中实现这些功能。

除此之外,所有其他类型的bug都受欢迎。

后记

这个crate的移植花了很长时间。主要是因为它确实是一个庞大的库。作为一个单打独斗的人,未来对break_eternity.js的更改移植也可能需要一段时间。

如果您有任何改进,请考虑贡献并积极提交pull请求。这将非常有帮助。

肯定会存在bug,尽管我非常愿意修复它们。

此外,如果您喜欢这个库,为什么不在这里给它一个星号,并在Patashu的break_eternity.js上留下评论?这将有助于提高我们包的知名度。

特别感谢

  • Patashu(为他花费时间编写这个巨大的库)
  • 纳鲁约科(用于OmegaNum.js的模实现,我毫不羞愧地复制了它)

依赖项

~0.7–7.5MB
~50K SLoC