Ruby 到底是怎么做到的? Jörg 或其他人是否知道幕后发生的事情?
不幸的是,我不太了解 C,所以 bignum.c
对我帮助不大。我只是有点好奇有人可以解释(用简单的英语)它使用的任何神奇算法背后的理论。
irb(main):001:0> 999**999
368063488259223267894700840060521865838338232037353204655959621437025609300472231530103873614505175218691345257589896391130393189447969771645832382192366076536631132001776175977932178658703660778465765811830827876982014124022948671975678131724958064427949902810498973271030787716781467419524180040734398996952930832508934116945966120176735120823151959779536852290090377452502236990839453416790640456116471139751546750048602189291028640970574762600185950226138244530187489211615864021135312077912018844630780307462205252807737757672094320692373101032517459518497524015120165166724189816766397247824175394802028228160027100623998873667435799073054618906855460488351426611310634023489044291860510352301912426608488807462312126590206830413782664554260411266378866626653755763627796569082931785645600816236891168141774993267488171702172191072731069216881668294625679492696148976999868715671440874206427212056717373099639711168901197440416590226524192782842896415414611688187391232048327738965820265934093108172054875188246591760877131657895633586576611857277011782497943522945011248430439201297015119468730712364007639373910811953430309476832453230123996750235710787086641070310288725389595138936784715274150426495416196669832679980253436807864187160054589045664027158817958549374490512399055448819148487049363674611664609890030088549591992466360050042566270348330911795487647045949301286614658650071299695652245266080672989921799342509291635330827874264789587306974472327718704306352445925996155619153783913237212716010410294999877569745287353422903443387562746452522860420416689019732913798073773281533570910205207767157128174184873357050830752777900041943256738499067821488421053870869022738698816059810579221002560882999884763252161747566893835178558961142349304466506402373556318707175710866983035313122068321102457824112014969387225476259342872866363550383840720010832906695360553556647545295849966279980830561242960013654529514995113584909050813015198928283202189194615501403435553060147713139766323195743324848047347575473228198492343231496580885057330510949058490527738662697480293583612233134502078182014347192522391449087738579081585795613547198599661273567662441490401862839817822686573112998663038868314974259766039340894024308383451039874674061160538242392803580758232755749310843694194787991556647907091849600704712003371103926967137408125713631396699343733288014254084819379380555174777020843568689927348949484201042595271932630685747613835385434424807024615161848223715989797178155169951121052285149157137697718850449708843330475301440373094611119631361702936342263219382793996895988331701890693689862459020775599439506870005130750427949747071390095256759203426671803377068109744629909769176319526837824364926844730545524646494321826241925107158040561607706364484910978348669388142016838792902926158979355432483611517588605967745393958061959024834251565197963477521095821435651996730128376734574843289089682710350244222290017891280419782767803785277960834729869249991658417000499998999
最佳答案
简单:从一年级开始,它就以您的方式进行操作。除了不以 10 为基数进行计算外,它以 40 亿为基数进行计算(和变化)。
想一想:使用我们的数字系统,我们只能表示从0
到9
的数字。那么,我们如何才能在不溢出的情况下计算6+7
呢?简单:我们确实实际上溢出了!我们不能将 6+7
的结果表示为 0
和 9
之间的数字,但我们可以溢出到下一个位置并将其表示为 0
和 9
之间的 两个 数字:3×100 + 1×10 1。如果你想添加两个数字,你从右边开始逐位相加,然后溢出(“进位”)到左边。如果要将两个数相乘,则必须将一个数的每一位分别与另一个数相乘,然后将中间结果相加。
BigNum 算术(这就是通常称为数字大于 native 数字的这种算术)的工作方式基本相同。除了基数不是 10,也不是 2,它是 native 机器整数的大小。因此,在 32 位机器上,它将是 base 232 或 4 294 967 296。
具体来说,在Ruby中Integer
实际上是一个永远不会实例化的抽象类。相反,它有两个子类,Fixnum
和 Bignum
,数字会根据它们的大小自动在它们之间迁移。在 MRI 和 YARV 中,Fixnum 可以保存 31 位或 63 位带符号整数(一位用于标记),具体取决于机器的 native 字大小。在 JRuby 中,Fixnum 可以容纳完整的 64 位带符号整数,即使在 32 位机器上也是如此。
最简单的操作是将两个数字相加。如果您查看 YARV 的 bignum.c 中 +
或 bigadd_core
的实现,这不是太不好的。我也看不懂 C,但您可以清楚地看到它是如何遍历各个数字的。
关于ruby - Ruby 的任意精度算术,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2867288/