Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/jquery-ui/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 为什么Haskell可以轻松处理非常大的数字?_Java_Programming Languages_Haskell_Biginteger - Fatal编程技术网

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

Java 为什么Haskell可以轻松处理非常大的数字?,java,programming-languages,haskell,biginteger,Java,Programming Languages,Haskell,Biginteger,为什么Haskell可以计算这么大的数字,而Java等其他语言却不能(这么容易)?简单而基本的答案是,它们实现了不同的默认整数。在Java中,标准int是32位。签名,这将为您提供一系列−2147483648至+2147483647 也就是说,Java也有类。如果你使用这些,你也将获得使用任意大数字的能力。这是一个如何编码数字的问题。传统的方法是用给定的位数对数字进行编码,这样就不能有无限的准确度。Haskell显然是通过对一个数字的可变位数来实现这一点的,这也很好,但通常意味着所有的数学运算都

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

简单而基本的答案是,它们实现了不同的默认整数。在Java中,标准int是32位。签名,这将为您提供一系列
−2147483648
+2147483647


也就是说,Java也有类。如果你使用这些,你也将获得使用任意大数字的能力。

这是一个如何编码数字的问题。传统的方法是用给定的位数对数字进行编码,这样就不能有无限的准确度。Haskell显然是通过对一个数字的可变位数来实现这一点的,这也很好,但通常意味着所有的数学运算都是在软件中完成的,因为硬件加速通常只适用于有限精度

它本可以将此功能构建到该语言中,但(与许多语言一样)它倾向于使基本功能紧密映射到CPU支持的事物上


另一方面,Haskell强调数学符号风格中的表达能力,其中“性能”方面的考虑在很大程度上是不相关的。

您可以使用BigInteger做同样的事情。Haskell是一种比Java更简洁的函数式语言

我们有这么多语言的一个原因是,不同的语言在不同的任务中表现得更好,因为它们是根据不同的假设设计的。大多数函数式语言在数学函数方面比较简单,但在其他用例方面比较困难,例如haskell不太可能是编写GUI的好选择。

Java有“原始数据类型”(处理器支持的类型)的概念,这些类型不同于所有其他类

在Haskell中,
Int
是一种与所有其他类型一样的类型,因此它很容易成为
Num
Integral
类型类的成员,这些类型在
(^)
”(^):(Num a,Integral b)=>a->b->a“
)中使用。这些类型类的另一个成员是
Integer
,它支持所有大小的整数(只要您有足够的内存存储它们的数字)


在Java中,您可以使用许多“大数字”库,但它们的操作不会使用您常用的中缀运算符,因为这些运算符仅适用于Java中的“基本类型”。

如前所述,如果您有32位字,并使用两个补码得到的完整范围-2^31到2^31-1

通过保留字的一些位,这些位可以用来携带值的类型信息。也就是说,值在运行时“知道”自己的类型。剩余的位用于携带值的数据

适合这些剩余位的整数值可以直接存储在字中。这种整数通常称为“fixnums”。如果它们不合适,则单词的类型位指示它是“bigint”,剩余的位用于将内存指针存储到存储bigint值的堆中

编译器需要将算术表达式转换为包含操作数允许的类型组合的多个代码路径。添加示例:

  • fixnum+fixnum
  • bigint+fixnum
  • fixnum+bigint
  • bigint+bigint

针对这些语言的编译器中的许多优化都集中在避免运行时类型检查的开销上,这些检查是实现这一功能所必需的。通常还有一些方法可以显式地告诉编译器,从fixnum到bignum的自动降级是不需要的,相反,我们需要32位整数的溢出行为。这对于高效地实现加密算法非常重要。

Haskell中的数字文字被重载,因此它们可以表示多种具体类型(如
Int
Integer
Float
甚至
MyOwnNumber

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

Hugs> 94535^445
1376320882321377050696053887661515621104890164005282153069726424773999801846841903244827702943487982707454966009456016735041878000604143500908532887464920380605164932112687039059526672109818924234920844448231612532570718657160234177285377733830104834041049076609912488237219608445995072867798430614935403219495883835042862802917980856774134757390782052200512932375660858045003581611863121089979673784484701791210379500218604466721285456487387736825167702127154268533859979529612671925052419513844416493584817268143587955662039327860394141299238613042312035808541735213479394437496215520277526351425482512084759462579494878772787079101513841720202004639843443083454387175700954018825292148776647553122504118229978165851660083576570848983047255050145168802863168613110619584686348869690774233051669081248424584219383477237544209892290799448207462345346336076966775224683516220960618177284844330167142846351091001423033864986042919757795382577032341453971393897073354841924116635150129850119992031076354249371062307034564093077675129303383786693131843907104175619570678630497198824622804914508555467550904967368926176118094672479099827962889569753303773699017596074205893197641101210911874606040804983166177455705972192827752532495287749766682029353154226049380290040508900715169403153139668217790502306177709467234413947747673881158973344492079455405942662489751581189327200960698310350121179918845099840977270519116578719881752429190273998774113278822810866144521416958558406602325070095207349450759264393913367193083149679216066539911941983836313340998945139132421885688290888674594474605510238217590823316979504437667252929278291853368754482552573193289277120902144178425726693671235675042499401282016643202758246845332593475338220708351934511933096882598943512036679145593929114103343255708217768511665236173107020739195152050863630870948954052925049746246549772984384435109578859863612603574306739909728739428192798727373799081111333186135697868385292787575475482883660605162944306327057220313320376280182432763977906971557137715710757099478269250731209785404487629107297262798803645379809868663503452656912571816192881412782623078761411808958183665272686617730596943579533808499348879195167683064937591552734375
这三个值具有不同的类型,对它们执行的操作将不同

Int
的确切大小取决于实现,但可以是28位,这种类型的行为类似于Java原语
Int
,例如,它将溢出

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

浮点
类似于Java
浮点
,使用浮点运算

和数字文字一样,许多运算符也重载(使用),所以可以和不同的类型一起使用。因此,
+
运算符可以同时使用
Int
s和
Float
s


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

这是设计理念的一个不同之处:

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

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

在每种语言中,都必须做一些特殊的事情才能得到另一种整数


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

我宁愿猜测Haskell提供了平滑的范围检查和数字转换,就像Lisp一样。只要您的数字保持在fixnum范围内,就可以进行计算
x = 4 :: Int
y = 4 :: Integer
z = 4 :: Float