咨询热线

082-114050170

网站公告: 诚信为本:市场永远在变,诚信永远不变。

第五系列

关于solidity中数值的复利计算教程_zoty中欧体育

时间:2024-12-10 22:01:01

   本文摘要:介 绍在上一篇文章中,我们辩论了百分比以及如何在Solidity中对其展开计算出来。

介 绍在上一篇文章中,我们辩论了百分比以及如何在Solidity中对其展开计算出来。在金融数学中,百分比一般来说与借贷和存款利息有关。

在每个时间段(例如一个月或一年)完结时,本金的一定百分比将缴纳给贷方或存款持有人。这种模式称作单利,每个期间缴纳的百分比称作定期利率。在计算机程序中,一般来说用于利率替换利率。例如对于3%的利率,比率为0.03。

因此可以将一个时期的利息缴纳金额计算出来为利率除以本金金额,从上一篇文章中我们早已告诉如何在Solidity中有效地而准确地做这一点。非常简单的利率模式很非常简单,但是如果不立刻将利息缴纳给贷方或存款持有人,而是将其加到本金上,情况就不会显得更为简单。

在这种情况下,过去期间积累的利息不会影响将来缴纳的利息。在本文中,我们辩论了如何在Solidity中构建此模式,该模式的名称为:复利。定期复利我们早已告诉如何计算出来单利。计算出来复利的必要方法是在每个时间段末计算出来单利,然后将计算出来出有的利加到本金上。

在高级语言(例如JavaScript)中,它看上去像这样:principal += ratio * principal; // Do after each time period这里的ratio完全意味著是分数,但是Solidity不反对分数,因此在Solidity中,我们应当这样写出:principal += mulDiv (ratio, principal, 10^18);我们用于上一篇文章中的mulDiv函数,并假设ratio是一个定点数,点后有18个小数。上面的代码在大多数情况下都可以用于,但是其+ =操作者可能会阻塞,因此为了保证代码的安全性,我们必须像这样展开变更:principal = add (principal, mulDiv (ratio, principal, 10^18));在本文中,为非常简单起见,我们将用于普通的算术运算,就像Solidity反对小数并且算术运算会阻塞一样。在实际代码中,这些操作者将被必要的功能代替。一旦我们告诉如何在单个期间内减少利息,问题就是:我们如何在每个时间段完结时启动时复利?与传统应用程序有所不同,智能合约无法具备任何后台活动。

智能合约的字节字节仅有在交易必要或通过另一个智能合约调用合约时才继续执行。人们可能会倚赖诸如Provable(以前称作Oraclize)之类的第三方服务来定期调用特定的智能合约,或者可能会从经济上鼓舞普通人这样做到。

这种方法有效地,但是有许多缺点。首先有人必需缴纳gas费,因此它不是免费的。

其次即使每个人在接下来的时间段内都无法访问改版的本金,也必需在每个周期完结时减少利息。第三时间周期越高,必需继续执行的配上混越频密,因此消耗的gas越少。第四此方法在较短的时间内不精确,因为事务挖出时间不能预测,并且在网络阻抗较高时可能会相当大。

因此,如果在每个时期的末尾展开复利不是Solidity的好主意,则我们什么时候应当加息?更佳的方法是只在有人必须提供本金或债务或存款的情况下才展开复利,并在此期间对所有完结的时间段展开复利,而不是在每个时间段末复利。最后一次:uint currentPeriod = block.timestamp / periodLength;for (uint period = lastPeriod; periodcurrentPeriod; period++) principal += ratio * principal;lastPeriod = currentPeriod;此代码将所有仍未复利的利息特到本金上,并且每次有人要采访本金时都必需继续执行。

这种方法被称作“惰性”填充,实际计算出来被延期到有人确实必须它们的结果之前。但是上面表明的“惰性”混合的构建不存在一个最重要问题。

实际的gas消耗量线性地各不相同自上次继续执行利息混合以来经过了多少时间间隔。如果时间段很短,或者上一次展开复利很长时间,则在所有经过的时间段内复利所需的燃气量可能会多达区块gas限额,从而实质上无法展开更进一步的复利。

所以问题是:如何更加有效地展开“惰性”填充?首先我们注意到,单个时间段内的复利可能会被这样改写:principal *= 1 + ratio;对于两个时间间隔,这将是:principal *= (1 + ratio) * (1 + ratio);然后我们注意到(1 + r)²= 1 +(2r +r²),因此双时间间隔的有效地利率为2r +r²,其中r是单时间间隔的利率。如果我们要引发兴趣的时间间隔数是偶数,我们可以通过将时间间隔持续时间加倍来将时间间隔数减为。当时间间隔的数量为奇数时,我们有可能只继续执行一次复利,从而使剩下的时间间隔数量为偶数。这是代码:function compound (uint principal, uint ratio, uint n)public pure returns (uint) { while (n0) {if (n % 2 == 1) { principal += principal * ratio; n -= 1;} else { ratio = 2 * ratio + ratio * ratio; n /= 2;} } return principal;}上面的代码具备对数复杂度,并且当本金和比率较小时效果很好,因此,principal * ratio乘积具备充足的有效地小数,以构建较高的精度。

但是如果principal和ratio较小,则上面的代码可能会产生不准确的结果。现在的问题是:如何提升延后复利的精度?在上面表明的代码中,精度在以下分开代码中:principal += principal * ratio;这是因为我们假设主体是整数,所以赋值必需近似值计算出来值。

近似值可能会多次继续执行,并且近似值误差不会特一起。为了解决问题这个问题,我们可能会注意到,在n个时间间隔内,利息可能会像这样简单:principal *= (1 + ratio) ** n;如果Solidity反对分数,则此代码将起起到,但只要不反对,我们就必须自己构建幂运算。我们用于与上一部分完全相同的对数复杂度方法,因此代码十分相近:function pow (uint x, uint n)public pure returns (uint r) { r = 1.0; while (n0) {if (n % 2 == 1) { r *= x; n -= 1;} else { x *= x; n /= 2;} }}function compound (uint principal, uint ratio, uint n)public pure returns (uint) { return principal * pow (1 + ratio, n);}留意表达式:r = 1.0。

这里要忘记,我们在这里处置分数时,样子Solidity显然反对它们,而实质上却不反对。人们将被迫用构建分数数学的函数来替换所有算术运算。

例如这是用于ABDK Math 64.64库的现实代码的外观,该库为64.64位定点数构建算术运算:function pow (int128 x, uint n)public pure returns (int128 r) { r = ABDKMath64x64.fromUInt (1); while (n0) {if (n % 2 == 1) { r = ABDKMath64x64.mul (r, x); n -= 1;} else { x = ABDKMath64x64.mul (x, x); n /= 2;} }}function compound (uint principal, uint ratio, uint n)public pure returns (uint) { return ABDKMath64x64.mulu (pow ( ABDKMath64x64.add (ABDKMath64x64.fromUInt (1),ABDKMath64x64.divu ( ratio, 10**18)), n),principal);}实质上,该库早已具备pow函数,可以用于它替换我们的构建。上面的代码十分准确和必要,但是仅有限于于线性时间间隔。如果我们必须在给定时间间隔内减少利息怎么办?这种模式被称作倒数复利倒数复利的点子是计算出来给定(而不是相同)时间段的利息。

构建此目的的一种方法是用于小数个周期。我们早已告诉如何计算出来n个周期的复利:principal *= (1 + ratio) ** n;假设时间段为一年,并且我们要计算出来1个月的复利,即一年的1/12。那么公式有误:principal *= (1 + ratio) ** (1 / 12);意外的是,以上右图的实体性和pow函数皆不反对分数指数。

我们可以通过整数幂和根或通过相同基数对数和指数来构建它们,但是是不是更加非常简单的方法来展开倒数填充?现实世界中的时间是倒数的,或者最少看上去是这样。以太坊中的时间是线性的。它以秒为单位,用整数回应。因此以1秒为周期展开定期复利就可以倒数展开复利,网卓新闻网,因为没人会在周期的中间仔细观察到本金。

乍一看,每秒复利的点子有可能看上去很怪异,但是在以太坊上,它的效果令人吃惊。3%的年利率实质上EOS0.000000093668115524%的每秒利率或0.000000000936681155每秒钟用18个小数回应的利率。

在这里,我们假设1年的时间为31556952秒。用于上述功能填充1年(31556952个周期),该比率得出结论2.99999999895%的年利率,因此精度完全超过10个有效数字。对于大多数应用程序来说早已充足了。用于128.128位定点数而不是64.64位或什至浮点数可以构建更高的精度。

在我们的实验中,填充1年的定期每秒利息消耗了约90Kgas。对于大多数应用于来说,这有可能是可以忍受的,但总的来说是很高的。在我们的下一篇文章中,我们将讲解获取完全完全相同精度的更加低廉的方法。

结论简单的分数计算出来(例如填充定期利率所需的分数计算出来)由于缺少本地分数数字反对而有可能对Solidity导致挑战。但是用于平方算法的幂运算和仿真的定点数依然可以有效地计算出来复利。

建议的方法功能强大,不足以在1年(甚至更长)的时间跨度内提升每秒的利率。然而这种方法非常乏gas。在下一篇文章中,我们将讲解更佳的方法,而下一个主题将是:指数和对数。


本文关键词:中欧体育,中欧体育(zoty),zoty中欧体育

本文来源:中欧体育-www.hnxl-edu.com

地址:黑龙江省佳木斯市连城县电李大楼4081号    电话:082-114050170    传真:0000-12345678
ICP备案编号:ICP备13715521号-4   Copyright © 2006-2024 www.hnxl-edu.com. 中欧体育科技 版权所有