使用Ruby进行任意精度算术
Ruby如何做到这一点? Jörg或其他任何人都知道幕后发生了什么吗?
不幸的是我不太了解C,所以bignum.c
对我没什么帮助。 我有点好奇,有人可以用简单的英语解释它使用的奇迹算法背后的理论。
irb(main):001:0> 999**999
简单:从一年级开始,它就像你一样。 除了它不在基数10中计算,它计算基数40亿(和变化)。
想一想:使用我们的数字系统,我们只能表示0
到9
数字。 那么,我们如何计算6+7
而不会溢出? 容易:我们确实溢出了! 我们不能将6+7
的结果表示为0
到9
之间的数字,但我们可以溢出到下一个位置并将其表示为0
到9
之间的两个数字:3×10 0 + 1×10 1 。 如果要添加两个数字,则从右侧以数字方式添加它们,并向左添加溢出(“进位”)。 如果要将两个数相乘,则必须将一个数字的每个数字分别乘以另一个数字,然后将中间结果相加。
BigNum算术(这是通常调用数字大于本机数的这种算法)基本上以相同的方式工作。 除了基数不是10,它不是2,它是 – 它是本机整数的大小。 因此,在32位机器上,它将是基本2 32或4 294 967 296。
具体来说,在Ruby中, Integer
实际上是一个永远不会被侮辱的抽象类。 相反,它有两个子类, Fixnum
和Bignum
,数字在它们之间自动迁移,具体取决于它们的大小。 在MRI和YARV中,Fixnum可以保存31或63位有符号整数(一位用于标记),具体取决于机器的本机字大小。 在JRuby中,Fixnum可以保存完整的64位有符号整数,即使在32位机器上也是如此。
最简单的操作是添加两个数字。 如果你看看YARV的bignum.c中+
或者更确切地说是bigadd_core
的实现 ,那么关注并不是太糟糕。 我也读不了C,但是你可以清楚地看到它是如何在各个数字上循环的。
你可以阅读bignum.c
的来源……
在非常高的层次上,没有进入任何实施细节, bignum
s是像你以前在小学一样“手工”计算的。 现在,肯定有许多可以应用的优化,但这是它的要点。
我不知道实现细节,所以我将介绍基本的Big Number实现如何工作。
基本上不依赖于CPU“整数”,它将使用多个CPU整数创建它自己。 为了存储arbritrary精度,可以说你有2位。 所以当前整数是11.你想要添加一个。 在正常的CPU整数中,这将翻到00
但是,对于大数,而不是滚动并保持“固定”整数宽度,它将分配另一个位并模拟一个加法,以便该数字变为正确的100。
尝试查看如何在纸上完成二进制数学运算。 转换为算法非常简单并且很简单。
Beaconaut APICalc 2于2011年1月18日刚刚发布,是一个用于bignum算法,密码分析和数论研究的任意精度整数计算器……
它使用Bignum类
irb(main):001:0> (999**999).class => Bignum
当然可以使用Rdoc