Ruby如何做到这一点? Jörg或其他任何人都知道幕后发生了什么吗?
不幸的是我不太了解C,bignum.c
对我没什么帮助。我有点好奇,有人可以用简单的英语解释它使用的任何奇迹算法背后的理论。
irb(main):001:0> 999**999
3680634882592232678947008400605218658383382320373532046559596214370256093004722315301038736145051752186913452575898963911303931894479697716458323821923660765366311320017761759779321786587036607784657658118308278769820141240229486719756781317249580644279499028104989732710307877167814674195241800407343989969529308325089341169459661201767351208231519597795368522900903774525022369908394534167906404561164711397515467500486021892910286409705747626001859502261382445301874892116158640211353120779120188446307803074622052528077377576720943206923731010325174595184975240151201651667241898167663972478241753948020282281600271006239988736674357990730546189068554604883514266113106340234890442918605103523019124266084888074623121265902068304137826645542604112663788666266537557636277965690829317856456008162368911681417749932674881717021721910727310692168816682946256794926961489769998687156714408742064272120567173730996397111689011974404165902265241927828428964154146116881873912320483277389658202659340 9310817205487518824659176087713165789563358657661185727701178249794352294501124843043920129701511946873071236400763937391081195343030947683245323012399675023571078708664107031028872538959513893678471527415042649541619666983267998025343680786418716005458904566402715881795854937449051239905544881914848704936367461166460989003008854959199246636005004256627034833091179548764704594930128661465865007129969565224526608067298992179934250929163533082787426478958730697447232771870430635244592599615561915378391323721271601041029499987756974528735342290344338756274645252286042041668901973291379807377328153357091020520776715712817418487335705083075277790004194325673849906782148842105387086902273869881605981057922100256088299988476325216174756689383517855896114234930446650640237355631870717571086698303531312206832110245782411201496938722547625934287286636355038384072001083290669536055355664754529584996627998083056124296001365452951499511358490905081301519892828320218919461550140343555306014771313976 6323195743324848047347575473228198492343231496580885057330510949058490527738662697480293583612233134502078182014347192522391449087738579081585795613547198599661273567662441490401862839817822686573112998663038868314974259766039340894024308383451039874674061160538242392803580758232755749310843694194787991556647907091849600704712003371103926967137408125713631396699343733288014254084819379380555174777020843568689927348949484201042595271932630685747613835385434424807024615161848223715989797178155169951121052285149157137697718850449708843330475301440373094611119631361702936342263219382793996895988331701890693689862459020775599439506870005130750427949747071390095256759203426671803377068109744629909769176319526837824364926844730545524646494321826241925107158040561607706364484910978348669388142016838792902926158979355432483611517588605967745393958061959024834251565197963477521095821435651996730128376734574843289089682710350244222290017891280419782767803785277960834729869249991658417000499998999
答案 0 :(得分:17)
简单:从一年级开始,它就像你那样做。除了它不在基数10中计算,它计算基数为40亿(并且变化)。
考虑一下:使用我们的号码系统,我们只能表示从0
到9
的数字。那么,我们如何计算6+7
而不会溢出?容易:我们做实际上溢出了!我们无法将6+7
的结果表示为0
和9
之间的数字,但我们可以溢出到下一个位置并将其表示为 2 <{em>} 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中,即使在32位机器上,Fixnum也可以保存一个完整的64位有符号整数。
最简单的操作是添加两个数字。如果您在YARV的bignum.c中查看+
或更确切地说bigadd_core
的实现情况,那么 也不会错过。我也读不了C,但是你可以清楚地看到它是如何循环的。
答案 1 :(得分:2)
您可以阅读bignum.c
...
在非常高的级别,没有进入任何实施细节,bignum
是“像手工”一样计算的,就像你在小学时所做的那样。现在,肯定可以应用许多优化,但这就是它的要点。
答案 2 :(得分:2)
我不知道实现细节,所以我将介绍基本的Big Number实现如何工作。
基本上不依赖于CPU“整数”,它将使用多个CPU整数创建它自己。为了存储arbritrary精度,可以说你有2位。所以当前整数是11.你想要添加一个。在正常的CPU整数中,这将翻转到00
但是,对于大数字,它不是翻转并保持“固定”整数宽度,而是分配另一个位并模拟一个加法,以便数字变为正确的100。
尝试查看如何在纸上完成二进制数学运算。转换为算法非常简单并且很简单。
答案 3 :(得分:1)
Beaconaut APICalc 2 刚刚于2011年1月18日发布,这是一个用于bignum算术,密码分析和数论研究的任意精度整数计算器......
答案 4 :(得分:0)