Skip to content

BigDecimal Builtins

Himxh edited this page Oct 4, 2026 · 1 revision

高精度计算 / BigDecimal Built-ins

浮点数的精度问题 / The Float Precision Problem

先看一段代码:

Consider this:

double a = 0.1 + 0.2;
runcmd("CONSOLE", "say " + a);

你以为会输出 0.3。实际会输出 0.30000000000000004。

You expect 0.3. You actually get 0.30000000000000004.

这不是 HimDSL 的 bug,是二进制浮点数的固有特性。0.1 在二进制里是无限循环小数,无法精确表示。绝大多数场景这点误差无所谓,但涉及金钱、积分、精确计数时,会累积成大问题。

This is not a HimDSL bug — it is a property of binary floating point. 0.1 has an infinite repeating representation in binary. Usually harmless, but money, points, and exact counts accumulate errors.

高精度计算的解决方案是用 BigDecimal——任意精度的十进制数。HimDSL 把它包装成五个函数。

The fix is BigDecimal — arbitrary-precision decimal numbers. HimDSL wraps five operations:


五个函数 / Five Functions

bigAdd(a, b)            // a + b
bigSub(a, b)            // a - b
bigMul(a, b)            // a * b
bigDiv(a, b)            // a / b,可指定精度
bigDivExact(a, b)       // a / b,必须整除

参数和返回值都是字符串。因为 BigDecimal 不是 HimDSL 的原生类型,用字符串传递最自然。

Arguments and return values are strings. BigDecimal is not a native HimDSL type; strings carry it naturally.

string a = bigAdd("0.1", "0.2");
runcmd("CONSOLE", "say " + a);       // "0.3"

结果精确,没有浮点误差。

The result is exact — no floating-point error.


参数与返回值 / Arguments and Returns

参数可以是字符串或数字。推荐用字符串,避免传参时已经是浮点数:

Arguments may be strings or numbers. Prefer strings, to avoid the value already being a float:

bigAdd("0.1", "0.2")        // ✓ "0.3"
bigAdd(0.1, 0.2)            // 0.1 和 0.2 已经是浮点,可能带误差

返回值总是字符串。要参与其他计算,转成数字:

Returns are always strings. Convert to numbers for further computation:

double d = toDouble(bigAdd("0.1", "0.2"));

但这样又回到浮点——只在真的需要数值时才转,否则保持字符串。

But that returns to floating point — convert only when truly needed.


bigDiv 的精度 / bigDiv Precision

普通除法 0.1 / 0.3 是无限循环小数,必须指定保留几位小数:

0.1 / 0.3 is a repeating decimal; specify how many fractional digits:

bigDiv("1", "3")            // "0.3333333333333333333333333333333333"(默认 34 位)
bigDiv("1", "3", 5)         // "0.33333",保留 5 位小数
bigDiv("1", "3", 2)         // "0.33"

第三个参数可选,默认 34 位。位数不足会四舍五入。

Third argument is optional; default 34. Truncation rounds to nearest.

bigDivExact 要求能整除,否则报错:

bigDivExact requires an exact division, or errors:

bigDivExact("6", "3")       // "2"
bigDivExact("1", "3")       // ✗ 报错:除不尽

使用 bigDivExact 表示"我认为这里能整除"。如果能整除,代码通过;如果条件变了不再整除,错误立即暴露。这比静默产生 34 位小数更安全。

Use bigDivExact when you expect exact division. It passes when exact, errors otherwise — safer than silently producing 34 digits.


一个实用的例子 / A Practical Example

累加玩家充值金额,需要精确到分:

Sum player payments, needing cent precision:

string total = "0";

void addPayment(string amount) {
    total = bigAdd(total, amount);
}

int main() {
    addPayment("19.99");
    addPayment("0.01");
    addPayment("5.50");
    // 用 double 会得到 25.500000000000004 或类似结果
    // 用 bigAdd 精确得到 "25.50"

    runcmd("CONSOLE", "say 累计充值: " + total);
}

钱永远不该用 double。这是整个软件行业的老规矩。

Money should never use double. An industry-wide rule.


什么时候用 / When to Use

用 / Use

  • 金钱、余额、交易。

  • 计分、积分,特别是累加很多次的时候。

  • 需要显示给用户的精确数值。

  • Money, balances, transactions.

  • Scores, points accumulated many times.

  • Precise values shown to users.

不用 / Do not use

  • 坐标、位置——这些本来就允许误差。

  • 概率、随机数——浮点的误差可忽略。

  • 性能敏感的循环——BigDecimal 比 double 慢得多。

  • Coordinates, positions — small errors are fine.

  • Probabilities, randomness — float error is negligible.

  • Performance-sensitive loops — BigDecimal is far slower than double.

默认用 double,只有明确需要精确时才上 big*。别为了方便把所有数字都变成 BigDecimal——那会让代码变慢,也更啰嗦。

Default to double; reach for big* only when precision is required. Do not turn every number into a BigDecimal — slower and noisier.


小结 / Summary

  • double 有精度问题,0.1 + 0.2 不等于 0.3。

  • 五个函数:bigAdd / bigSub / bigMul / bigDiv / bigDivExact。

  • 参数和返回值都是字符串。

  • bigDiv 默认保留 34 位,可指定精度。

  • bigDivExact 要求整除,否则报错。

  • 钱必须用 big*。

  • 坐标、概率、性能敏感场景继续用 double。

  • double has precision issues; 0.1 + 0.2 != 0.3.

  • Five functions: bigAdd / bigSub / bigMul / bigDiv / bigDivExact.

  • Arguments and returns are strings.

  • bigDiv defaults to 34 digits; precision is configurable.

  • bigDivExact requires exact division.

  • Money must use big*.

  • Coordinates, probabilities, performance-sensitive paths use double.


下一步 / Next Steps

下一章 [字符串函数 / String-Builtins] 是速查表,详细讲解见《字符串与字符》。

Next, [字符串函数 / String-Builtins] is a lookup, with details in Strings & Chars.


HimDSL 文档 / Documentation

入门 / Getting Started

语言基础 / Language Basics

控制流 / Control Flow

函数 / Functions

数据结构 / Data Structures

自定义类型 / Custom Types

Minecraft 集成 / Minecraft Integration

事件与调度 / Events & Scheduling

GUI 系统 / GUI System

内置函数参考 / Built-ins Reference

进阶 / Advanced

扩展 API / Extension API

你真的需要 API 吗?/ Do you really need the API?

Clone this wiki locally