以太坊中的许多操作都是对超出JavaScript安全值范围的数字进行操作。
BigNumber是一个可以安全地对任意大小的数字进行数学运算的对象。
大多数需要返回值的操作将返回一个BigNumber,接受值的参数通常会接收它们。
这个库中的许多函数和方法都接受可以无歧义(non-ambiguously)且安全地转换为BigNumber的值。这些值可以指定为:
HexString或decimal string,两者都可以为负数。
一个BytesLike对象,例如数组或Uint8Array。
一个大数(BigNumber)实例。
一个在JavaScript numbers的安全范围内的数字。
在支持BigInt的环境中的一个JavaScript BigInt对象。
BigNumber的构造函数不能被直接调用。相反,使用静态BigNumber.from
。
为aBigNumberish返回一个BigNumber的实例。
例子:
BigNumber类是不可变的,所以没有任何操作可以改变它所表示的值。
返回值为BigNumber + otherValue的BigNumber。
返回值为 BigNumber - otherValue的BigNumber。
返回值为 BigNumber × otherValue的BigNumber。
返回值为 BigNumber ÷ divisor的BigNumber。
返回值为 BigNumber ÷ divisor余数的BigNumber。
返回值为 BigNumber 指数的幂为exponent的BigNumber。
返回值为绝对值的BigNumber。
返回一个BigNumber,其BigNumber的值超出bitcount最低有效位的位则设为0。
Two's Complement是一种优雅的方法, 用于编码和解码固定宽度的有符号值,同时有效地保留数学运算。大多数用户不需要与它们交互。
返回一个BigNumber, BigNumber的值由带位宽(bitwidth)的二进制补码转换而来。
返回一个BigNumber, BigNumber的值转换为带位宽的二进制补码。
当且仅当BigNumber的值等于otherValue时返回true。
当且仅当BigNumber的值<otherValue时返回true。
当且仅当BigNumber的值≤otherValue时返回true。
当且仅当BigNumber的值>otherValue时返回true。
当且仅当BigNumber的值≥otherValue时返回true。
当且仅当BigNumber的值为0时返回true。
在支持BigInt的平台上以JavScript BigInt值返回BigNumber的值。
将BigNumber的值转换JavaScript值。
如果该值大于Number.MAX_SAFE_INTEGER或小于等于Number.MIN_SAFE_INTEGER, 则会抛出一个错误。
以十进制字符串的形式返回BigNumber的值。
返回BigNumber的值为十六进制的值,0x
是前缀DataHexString.。
当且仅当对象是BigNumber是对象时返回true。
这部分是针对一些经常出现的问题。
许多人在处理以太坊时遇到的第一个问题是数字的概念。 大多数常见的货币被划分成非常小的粒度。例如,1美元只有100美分。然而,一个ether等于1018 wei。
JavaScript使用IEEE 754 double-precision binary floating point](link-wiki-ieee754)来表示数值。 因此,在9,007,199,254,740,991之后的整数集就存在漏洞了; 这对以太坊来说是个问题,即使是9,007,199,254,740,991数值也才只有0.009以太(单位:wei), 这意味着超过这个值将开始产生舍入误差。
用代码来说明这个问题,如下:
为了修复这一点,所有的数字(可以很大)都被存储和操作为Big Numbers](BigNumber)。
函数parseEther( etherString )和formatEther( wei ) 可以用字符串(用户可以查看或输入)和Big Number(可以安全地进行数学操作)之间进行转换。
每个人都有自己最喜欢的Big Number库,一千个读者就有一千个哈姆雷特, 就像他们的编辑器都有vi vs emacs。在npm上有超过100个Big Number库。
Ethers 大数(BigNumber)对象和其他库之间最大的区别之一是它是不可变的,这在处理区块链的异步特性时非常重要。
在异步函数中捕获值是不安全的,所以不可变性可以让我们不容易犯错误,这在支持大量就地操作的低级库上是不可能得到保证的。
其次,Ethers 大数(BigNumber)提供了内部所需的所有功能,通常对大多数开发人员来说应该足够了, 而不暴露一些更高级和罕见的功能。因此,在不影响用户的情况下,交换底层库将更加容易。
例如,如果BN.js被公开,有人可能会使用最大的公分母函数, 这将是替换库也应该提供的功能,以确保不会影响依赖于该功能的开发人员。
BN.js之所以在内部被用作big number,是因为它是elliptic使用的库。
因此,无论如何都必须包含它,所以我们利用这个库,而不是添加另一个Big Number库,添加了就意味着两个不同的库提供相同的功能。
与其他库(包括用于各种目的的单独的Big Number库)相比,这节省了大约85kb(该库大小的80%)的库大小。
有些人经常提到希望指定一个用户定义的全局 Big Number库,所有函数都将返回这个库。
这是有问题的,因为您的代码可能与其他使用Ethers的库或代码共存。事实上,甚至Ethers也在内部使用了许多公共函数。
例如,如果你使用的库使用的是a.plus(b)
而不是a.add(b)
,这将在尝试内部计算fees时Ethers会被破坏,而其他库可能有类似的逻辑。
但是,大数(BigNumber)原型是公开的,所以你总是可以添加一个toMyCustomBigNumber()
方法到所有全局的大数(BigNumber)会更安全。