为什么Haskell可以轻松处理非常大的数字?

n00*_*ki3 26 java haskell programming-languages biginteger

Hugs> 94535^445
1376320882321377050696053887661515621104890164005282153069726424773999801846841903244827702943487982707454966009456016735041878000604143500908532887464920380605164932112687039059526672109818924234920844448231612532570718657160234177285377733830104834041049076609912488237219608445995072867798430614935403219495883835042862802917980856774134757390782052200512932375660858045003581611863121089979673784484701791210379500218604466721285456487387736825167702127154268533859979529612671925052419513844416493584817268143587955662039327860394141299238613042312035808541735213479394437496215520277526351425482512084759462579494878772787079101513841720202004639843443083454387175700954018825292148776647553122504118229978165851660083576570848983047255050145168802863168613110619584686348869690774233051669081248424584219383477237544209892290799448207462345346336076966775224683516220960618177284844330167142846351091001423033864986042919757795382577032341453971393897073354841924116635150129850119992031076354249371062307034564093077675129303383786693131843907104175619570678630497198824622804914508555467550904967368926176118094672479099827962889569753303773699017596074205893197641101210911874606040804983166177455705972192827752532495287749766682029353154226049380290040508900715169403153139668217790502306177709467234413947747673881158973344492079455405942662489751581189327200960698310350121179918845099840977270519116578719881752429190273998774113278822810866144521416958558406602325070095207349450759264393913367193083149679216066539911941983836313340998945139132421885688290888674594474605510238217590823316979504437667252929278291853368754482552573193289277120902144178425726693671235675042499401282016643202758246845332593475338220708351934511933096882598943512036679145593929114103343255708217768511665236173107020739195152050863630870948954052925049746246549772984384435109578859863612603574306739909728739428192798727373799081111333186135697868385292787575475482883660605162944306327057220313320376280182432763977906971557137715710757099478269250731209785404487629107297262798803645379809868663503452656912571816192881412782623078761411808958183665272686617730596943579533808499348879195167683064937591552734375
Run Code Online (Sandbox Code Playgroud)

为什么Haskell可以计算如此大的数字,而其他语言(例如Java)不能(如此容易)?

Nor*_*sey 42

这是设计理念不同之处:

  • Haskell的设计者希望确保用户不会对需要超过32位的整数计算看似任意的失败感到惊讶.

  • Java的设计者希望确保用户不会因为对需要超过32位的整数进行大量计算而导致看似随意的性能下降而感到惊讶.

在每种语言中,你必须做一些特殊的事情来获得另一种整数.

默认情况下,支持任意大整数的语言有悠久而光荣的历史.我最喜欢的两个是IconSmalltalk,它们都已超过25年.

  • 虽然Haskell中的"特殊内容"有点容易:它只是意味着使用,例如,`Int32`作为你的类型,而在Java中,我的理解是缺乏运算符重载会迫使你不得不说像`x这样的东西. add(y)`或`x.multiply(y)` (10认同)
  • Common Lisp ftw:D (2认同)

Dan*_*ker 26

Java有BigInteger类.

它可以将这个工具构建到语言中,但是(像许多语言一样)它往往使原始特征紧密地映射到CPU支持的东西上.

另一方面,Haskell强调数学符号风格的表达性,其中"性能"考虑因素在很大程度上是无关紧要的.

  • 但需要明确的是:Haskell开发人员通常不认为性能考虑是无关紧要的. (23认同)

Tom*_*rst 11

在Haskell数字文字被重载,以便它们可以代表多个具体类型(如Int,Integer,Float或甚至MyOwnNumber).

您可以通过提供类型信息手动选择特定类型,如下所示:

x = 4 :: Int
y = 4 :: Integer
z = 4 :: Float
Run Code Online (Sandbox Code Playgroud)

这三个值具有不同的类型,并且对这些值执行的操作将表现不同.

a的确切大小Int是依赖于实现的,但可以是28位,这种类型的行为类似于Java原语int,例如它会溢出.

An Integer是一种可以包含任意精度整数的类型,如Java BigInteger.

而a Float就像一个Java float,使用浮点运算.

就像数字文字一样,许多运算符也会被重载(使用类型类),因此可以与不同的类型一起使用.因此,+操作员可以同时使用Ints和Floats.

在您的情况下,由于您没有提供任何类型信息,解释器将默认为该Integer类型.这意味着对于^操作员,它也将选择Integer实例.允许任意精度的整数计算.


yai*_*chu 6

Java具有"原始数据类型"(处理器支持的类型)的概念,并且与所有其他类不同.

在Haskell中,Int类似于所有其他类型,因此它很容易成为()中使用的类NumIntegral类的成员.这些类型类的另一个成员是,它支持所有大小的整数(只要你有足够的数字内存).(^)"(^) :: (Num a, Integral b) => a -> b -> a"Integer

在Java中,您可以使用许多"大数字"库,但是它们的操作不会使用您习惯的中缀运算符,因为它们仅用于Java中的"原始类型".

  • @harms:Haskell在编译时进行类型推断和类型检查.在这种情况下,由于没有提供类型信息,它将默认为"Integer"(类似于Java`BigNumber`).但是,您可以手动添加类型信息,以表示数字是"Int"(如Java原语`int`),在这种情况下,`^`操作的结果将简单地溢出并产生不正确的`Int`结果. (4认同)