Perl使用Math::BigInt执行连续算术运算结果不符合预期问题
问题原因
你遇到的现象是Math::BigInt的运算方法的默认特性导致的,和你操作顺序无关。
核心原理
Math::BigInt中所有以b开头的内置运算方法(badd/bmuladd/bsub等)默认都是原地修改调用对象本身,且返回值是修改后的对象自身的引用,不会生成新的独立对象。
你的代码中my $y = $x->badd(1);执行后,$y和$x指向的是同一个Math::BigInt实例,并没有生成独立的新值。后续执行$x->bmuladd(2,-1)修改了这个实例的数值,$y指向的内容自然也会同步变动,所以最后打印时两个变量输出的是同一个实例的最终值,结果完全相同。
你单独执行一个操作能得到正确结果,是因为没有后续的修改操作覆盖对象的值;把$y的打印语句放到最后结果不符合预期,以及你还原$x值时$y也跟着变,都是多个变量共享同一个对象实例导致的。
正确实现方式
有两种常用的方案可以得到你预期的结果:
方案1:调用copy()方法生成独立对象再运算
每次运算前先克隆原对象,在新对象上做运算,不会影响原对象和其他变量:
use strict; use warnings; use Math::BigInt; my $k = '1329227995784915872903807060280344577'; my $x = Math::BigInt->new($k); # 拷贝x后再做加1运算,y是独立对象 my $y = $x->copy()->badd(1); # 拷贝x后再做乘加运算,z是独立对象 my $z = $x->copy()->bmuladd(2,-1); print "value to variable z $z\n"; print "value to variable y is $y\n";
方案2:使用重载的普通算术运算符
Math::BigInt已经重载了常规的算术运算符,用普通运算符运算会自动生成新的独立对象,不会修改原对象:
use strict; use warnings; use Math::BigInt; my $k = '1329227995784915872903807060280344577'; my $x = Math::BigInt->new($k); my $y = $x + 1; my $z = $x * 2 - 1; print "value to variable z $z\n"; print "value to variable y is $y\n";
两种方案的输出都完全符合你的预期。
内容的提问来源于stack exchange,提问作者7beggars_nnnnm
相关产品推荐
相关产品推荐

