ALEO 中的定点运算

Justin | Aleo 中文
Aleo中文社区(非官方)
6 min readApr 17, 2023

这篇博文由 Aleo 社区成员 zk_tutorials 撰写

您是否有兴趣学习如何制作基于区块链的系统来保证隐私和可扩展性,使其能够执行机器学习等复杂任务?编程语言 LEO 简化了基于 ZKP 的程序的编程,但默认情况下仅支持基于整数类型的数字。本文分析了使用 LEO 的 zkSNARKS 中定点数的设计,它允许使用分数进行计算,适用于广泛的应用程序。了解如何表示小数并考虑可存储值的范围与所表示数字的准确性之间的权衡。这些知识对于任何在 zkSNARKs 中构建复杂程序的人来说都是有价值的。

介绍

基于区块链的系统正在我们生活的许多部分出现,例如 DeFi 或游戏行业。然而,许多现代区块链需要更多的隐私和可扩展性,从而限制了用例的范围。零知识证明和由零知识证明支持的区块链,如 Aleo,承诺提供更好的可扩展性和隐私保证,并支持新颖的区块链应用程序。这包括新颖的 DeFi 应用程序、更复杂的 web3 游戏或基于人工智能的程序。其中许多应用程序需要表示各种数字,包括小数。Aleo 附带了一种编程语言 Leo,它极大地简化了基于零知识的程序的编程。但是,它仅支持基于整数类型的数字。在本文中,

定点数的简单实现

在实现定点数表示法时,我们可以使用 Leo 语言为变量提供的整数类型。此外,我们在内部指定了一个比例因子,它定义了为值小数点左侧的整数部分保留的数字,还定义了值小数点右侧的小数部分。假设我们要将值 1.55 表示为小数点后两位精度的定点数。为此,我们可以引入一个变量 i 并分配 155,即值 1.55 乘以比例因子 100:

我们现在可以使用此变量执行数学运算。例如要加0.45,我们在程序代码中加上45(.45*100),得到的变量值为200。在解释程序的输出时,我们需要将该值除以比例因子100获得所需的小数点表示法 — 加法结果在小数点表示法中为 2。

同样,我们也可以进行乘法运算。乘以十进制的2.50时,乘以定点形式的250,再除以比例因子100。例如,小数形式的2*2.5=5就是200*250/100 =500 定点表示法。同样,当在定点符号之外解释结果时,我们需要将定点数 500 除以比例因子 100 以获得预期结果 5。

对于除法,我们进行类似于乘法的处理,但乘以比例因子而不是除法。

例如,小数点表示法中的 4.5/0.5 = 9 表示定点数表示法中的 100*450/50 = 900。除以缩放因子,我们得到预期结果 9。

概括和需要考虑的事情

上面的例子表明比例因子定义了小数部分的位数。对于 n 个小数位,我们使用了 10的n次方的比例因子。通常,比例因子越高,精度越高;但是,我们需要记住该类型的有效值范围。

在上面使用u32的例子中,一般范围在0到2的32次方 -1=4,294,967,295之间。由于类型的二进制性质,一个常见的概念是使用 2 的幂的比例因子 S。当使用比例因子2的5次方=32时,小数部分使用5位,整数部分仅保留27位。因此,整数部分的最大数为2的27次方-1=134,217,727,小数部分的分辨率为1/2 5 =1/32。小数部分可以在最大整数上加上31/32,所以最大可表示值介于0和2的27次方 -1+31/32=134,217,727.969之间。

同时,最大表示误差被计算为(1/S)/2,所以在这个例子中,它是(1/2 5 )/2=1/64=0.015625。因此,更广泛的比例因子使我们能够拥有更准确的小数表示,但会减少整数部分的大小,从而减少可表示的值范围。

正如我们所看到的,在我们可以存储的值的范围和我们表示的数字的准确性之间存在权衡。

特别是在乘法或除法时,我们可能会遇到溢出。例如,假设我们有一个比例因子2的5次方 =32,并且我们想要将2的16次方 =65536 乘以2的6次方 =64。下面的代码尝试这样做。

对于定点表示法,我们必须将两个数字都乘以比例因子,然后将 2的21次方乘以2的11次方,然后再除以比例因子2的5次方。仅通过查看说明,我们就可以预期代码输出为2的27次方。

但是,当我们查看输出时,我们得到以下信息:

c * d 的临时结果是 2的32次方,刚好超出 u32 类型的范围。因此,我们得到了数字溢出并得到了错误的结果。

那么我们能做些什么呢?我们可以对所有类型(变量和输出)使用 u64 类型而不是 u32 类型,它可以存储最多2的64次方 -1 的数字。这样,我们得到了 2的27次方的预期结果:

请记住,我们需要再次除以比例因子才能用正常术语解释定点数结果:2的27次方 / 2的5次方 = 2的22次方,这是上述计算 2的16次方乘以 2的6次方的结果。

然而,通过使用 u64,电路大小从 96 个约束增加到 192 个约束,有效地增加了一倍。这会导致更高的证明成本,尤其是在复杂的应用中。因此,另一种方法是降低比例因子,从而可能降低数字表示的准确性。

当使用 2的4次方作为比例因子而不是2的5次方且只有 u32 类型时,我们得到以下输出:

此输出为2的26次方。同样,将它除以比例因子2的4次方,我们得到预期的正确输出2的22次方。

该代码通常也适用于负数。但是,我们需要使用有符号整数类型。考虑到符号需要一个额外的位,因此对于 i32,整数部分的范围计算为 +- 2 31 -1,转换为 -2147483648 到 2147483647 之间的范围。

示例代码

定点格式的两个数字 a 和 b 相加:

两个数 a 和 b 的定点格式相乘:

定点格式的两个数 a 和 b 的除法:

您可以在这个 GitHub 页面上找到整个 Leo 项目代码。

--

--