欧宝体育-欧宝体育娱乐-欧宝体育平台 / Blog / 基础教育 / 关于solidity中数值的百分比和比例问题【欧宝体育】

关于solidity中数值的百分比和比例问题【欧宝体育】

欧宝体育娱乐

欧宝体育娱乐-金融数学的基本解释从百分比开始。y的x百分比是多少?x占y的百分比是多少?我们都告诉答案:y的x百分比是xy100,y是y100x百分比。

这是学校学的数学。以上公式类似于求解尺度。一般来说,比例是以下形式的方程:ab=cd,拒绝求解比例就是找一个告诉其他三个值的值。

比如d可以从a,b,c中找到,如下右图所示:d=b c a,如上一篇文章所示,在主流编程语言中简单明了,在Solidity中计算,挑战性惊人。原因有二:I)实体不反对评分;Ii)数字类型ii)坚固性可能被阻止。在Javascript中,x y z: x * y/z的计算非常简单。

值得信赖,这个表达式会通过安全审查,因为x和y的相乘很可能被阻塞,所以计算结果可能不准确。在SafeMath中使用时帮助不大,因为即使最终结果是256位也不会结束事务。在上一篇文章网卓新闻网中,我们把这种情况称为“幻影屏蔽”。

像x/z * y或y/z * x这样在乘法之前展开乘法,可以解决幻像遮挡的问题,但可能会导致精度下降。在这篇文章中,我们找到了更好的方法来处理实度中的百分比和比例。本文的目的是在Solidity中构建以下函数:function muldiv (uint x,uint y,uint z) public pure returns (uint),它将计算xyz,对结果进行舍入,如果z为零的结果不适合uint,则将其丢弃。

先说下面这个很简单的解决方案:function muldiv (uint x,uint y,uint z)public pure returns(uint){ return x * y/z;}这个解决方案基本符合大多数拒绝:也许计算xyz,将结果四舍五入,如果z为零就扔掉。不过没有问题:它实际上是计算x y mod 2 z的,这就是实度中乘法分块的工作原理。

当乘法结果不适合256位时,只返回少于256位的结果。对于较小的x和y值,当xy ^ 2时没有区别,但是对于较小的x和y值,这将产生错误的结果。所以第一个问题是:如何才能避免堵塞?在Solidity中避免乘法阻塞的常用方法是SafeMath库中的mul函数:function muldiv (uint x,uint y,uint z)public pure returns(uint){ return mul(x,y)/z;}这个代码保证了结果的准确性,所以现在所有的拒绝可能都是一致的,对吗?没那么慢。

如果结果不适合uint,则拒绝被恢复,并且该构建可能满足要求。但即使最终结果合适,当xy不适合uint时,这个构造也不会恢复到。我们称这种情况为“幻影阻挡”。

在上一篇文章中,我们展示了如何以牺牲准确性为代价来解决错觉阻挡的问题,但是这个解决方案在这里不起作用,因为我们必须获得准确的结果。既然不能恢复到幻影挡,那如何防止幻影挡,保持精度呢?我们展开下面的替换:x=az b,y=cz d,其中A,B,C,D为整数,0bz,0dz。

那么:xyz=(azb)(cZD)z=(abz(adbc)zbd)z=abzadbCBd因此,函数可以改写为:function muldiv (uint x,uint y,uint z)public pure returns(uint){ uint a=x/z;uint b=x % z;//x=a * z b uint c=y/z;uint d=y % z;//y=c * z d返回a * b * z a * d b * c b * d/z;}这里我们使用了common和*运算符来提高可读性,而SafeMath函数中不应该使用实数代码来避免实数(即非虚数)阻塞。在这个构造中,幻影分块还是可以的,只是在最后一项:b * d/z,但是由于B和D都大于Z,所以可以保证z212时代码可以长时间工作,所以可以保证bd适合256位。
因此,当未知z不到2 ^ 128时,可以用于这种构造。罕见的例子是18位小数的定点乘法:x y 10。

怎样才能完全避免幻影阻挡?错觉分块问题的根源是中间乘法结果不适合256位。因此,让我们将其用于更一般的类型。

实性本身并不反对小于256位的数字类型,所以我们将被迫模拟它们。我们基本上需要两个运算符:uintuintwide and wideuintuint。因为两个256位无符号整数的乘积不能大到512位,所以宽类型必须至少有512位宽。我们可以用两对256位无符号整数来模拟512位无符号整数,它们分别保存整个512位数字的低256位和低256位。

因此,代码可能看起来像右图:function muldiv (uint x,uint y,uint z)public pure returns(uint){(uint l,uint h)=full mul (x,y);返回fullDiv (l,h,z);}这里,fullMul函数将两个256位无符号整数相加,并将结果分成两个256位部分,作为一个512位无符号整数。fullDiv函数将512位无符号整数DFT作为两个256位无符号整数传输,但将其作为256位无符号整数传输,并将结果作为256位无符号整数返回。让我们用学校数学的方式构造这两个函数:函数full mul (uint x,uint y)公共纯收益(uint l,uint h){ uint XL=uint 128(x);uint xh=x128uint yl=uint 128(y);uint yh=y128uint xlyl=xl * yluint xlyh=xl * yhuint xhyl=xh * yluint xhyh=xh * yhuint ll=uint 128(xlyl);uint LH=(xlyl 128)uint 128(xlyh)uint 128(xhyl);uint HL=uint 128(xhyh)(xlyh 128)(xhyl 128);uint hh=(xhyh 128);l=ll(LH 128);h=(LH 128)HL(hh 128);}和function full div (uint l,uint h,uint z)public pure returns(uint r){ require(Hz);uint zSshift=MostItalicantbit(z);uint shift dz=z;if(zShIFT=127)zShIFT=0;else { zShIFT-=127;shift dz=(shift dz-1zShift)1;} while(h0){ uint lsshift=MostItalicantbit(h)1;uint hs shift=256-ls shift;uint e=((hhShift)(llShIFT))/ShIFT dz;if(LShifTzShShIFT)e=(LSShShShShShShShShShT);else=(zShIFT-lsShIFT);r=e;(uint tl,uint th)=fullMul (e,z);h-=th;if(tll)h-=1;l-=TL;} r=l/z;} mostSignificantBit这里是一个函数,返回参数最低有效位置的从零开始的索引。

该函数可以通过以下方式构造:function most significant bit(uint x)public pure returns(uint r){ require(x0);if(x=2 * * 128){ x=128;r=128} if(x=2 * * 64){ x=64;r=64} if(x=2 * * 32){ x=32;r=32} if(x=2 * * 16){ x=16;r=16} if(x=2 * * 8){ x=8;r=8;} if(x=2 * * 4){ x=4;r=4;} if(x=2 * * 2){ x=2;r=2;} if(x=2 * * 1){ x=1;r=1;}}上面的代码很简单,可能要解释一下,但是现在我们就跳过解释,重点讲不同的问题。这段代码的问题是,每次调用mulDiv函数消耗大约2.5K的汽油,相当多。那么,我们能有一个低价格吗?下面的代码是基于Remco Bloemen描述的激动人心的数学发现的。

首先重写fullMul函数:function fullmul (uint x,uint y) public pure returns (uint l,uint h) {uint mm=mulmod (x,y,uint(-1));l=x * y;h=mm-l;if(MML)h-=1;}每次fullMul通话可节省约250加仑汽油。然后我们重写muldiv函数:mulDiv函数(uint x,uint y,uint z)public pure returns(uint){(uint l,uint h)=full mul (x,y);要求(Hz);uint mm=mulmod (x,y,z);if(MML)h-=1;l-=mm;uint pow 2=z-z;z/=pow 2;l/=pow 2;l=h *(pow 2-/pow 2-1);uint r=1;r *=2-z * r;r *=2-z * r;r *=2-z * r;r *=2-z * r;r *=2-z * r;r *=2-z * r;r *=2-z * r;r *=2-z * r;返回l * r;}这个构建每次mulDiv调用只消耗550左右的汽油,可以进一步优化。

比学校的数学方法好五倍。非常好!但本质上写这样的代码是需要获得数学博士学位的,并不是每个问题都有这样的数学解。

如果可以,事情不会简单很多。正如我们在本文末尾所说,在JavaScript中,只写了一个*b/c,其余的由语言处理。如果我们能为稳固做点什么呢?本质上,我们可以。

虽然核心语言不反对浮点,但有些库反对。例如,对于ABDKMathQuad库,可以写:function mulDiv (uint x,uint y,uint z)public pure returns(uint){ returnbdkmasthquad . touint(abdkmasthquad . div(abdkmasthquad . mul(abdkmasthquad . Fromuint(x),abdkmasthquad . Fromuint(y)),abdkmasthquad . Fromuint(z));}不像JavaScript那么优雅,不像mathemagic求解那么便宜(甚至比学校的数学方法更具扩展性),但是非常简单准确,因为四精度浮点数中大约有33个有效小数。

这种构造方法消耗的气体有一半以上用于将uint值切换为浮点数和浮点数,计算出的比例仅为消耗1.4K左右的气体。因此,所有智能契约中使用的浮点数可能比混合整数和浮点数便宜得多。结论由于拦网和缺乏得分对抗,百分比和比例在稳健性上可能具有挑战性。但是各种数学技巧都可以准确有效的解决问题比例的问题。

本文来源:欧宝体育-www.demaxconstruction.com

相关文章

网站地图xml地图