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

发布于 2024-07-29 16:19:53 字数 2315 浏览 5 评论 0原文

Hugs> 94535^445
1376320882321377050696053887661515621104890164005282153069726424773999801846841903244827702943487982707454966009456016735041878000604143500908532887464920380605164932112687039059526672109818924234920844448231612532570718657160234177285377733830104834041049076609912488237219608445995072867798430614935403219495883835042862802917980856774134757390782052200512932375660858045003581611863121089979673784484701791210379500218604466721285456487387736825167702127154268533859979529612671925052419513844416493584817268143587955662039327860394141299238613042312035808541735213479394437496215520277526351425482512084759462579494878772787079101513841720202004639843443083454387175700954018825292148776647553122504118229978165851660083576570848983047255050145168802863168613110619584686348869690774233051669081248424584219383477237544209892290799448207462345346336076966775224683516220960618177284844330167142846351091001423033864986042919757795382577032341453971393897073354841924116635150129850119992031076354249371062307034564093077675129303383786693131843907104175619570678630497198824622804914508555467550904967368926176118094672479099827962889569753303773699017596074205893197641101210911874606040804983166177455705972192827752532495287749766682029353154226049380290040508900715169403153139668217790502306177709467234413947747673881158973344492079455405942662489751581189327200960698310350121179918845099840977270519116578719881752429190273998774113278822810866144521416958558406602325070095207349450759264393913367193083149679216066539911941983836313340998945139132421885688290888674594474605510238217590823316979504437667252929278291853368754482552573193289277120902144178425726693671235675042499401282016643202758246845332593475338220708351934511933096882598943512036679145593929114103343255708217768511665236173107020739195152050863630870948954052925049746246549772984384435109578859863612603574306739909728739428192798727373799081111333186135697868385292787575475482883660605162944306327057220313320376280182432763977906971557137715710757099478269250731209785404487629107297262798803645379809868663503452656912571816192881412782623078761411808958183665272686617730596943579533808499348879195167683064937591552734375

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

Hugs> 94535^445
1376320882321377050696053887661515621104890164005282153069726424773999801846841903244827702943487982707454966009456016735041878000604143500908532887464920380605164932112687039059526672109818924234920844448231612532570718657160234177285377733830104834041049076609912488237219608445995072867798430614935403219495883835042862802917980856774134757390782052200512932375660858045003581611863121089979673784484701791210379500218604466721285456487387736825167702127154268533859979529612671925052419513844416493584817268143587955662039327860394141299238613042312035808541735213479394437496215520277526351425482512084759462579494878772787079101513841720202004639843443083454387175700954018825292148776647553122504118229978165851660083576570848983047255050145168802863168613110619584686348869690774233051669081248424584219383477237544209892290799448207462345346336076966775224683516220960618177284844330167142846351091001423033864986042919757795382577032341453971393897073354841924116635150129850119992031076354249371062307034564093077675129303383786693131843907104175619570678630497198824622804914508555467550904967368926176118094672479099827962889569753303773699017596074205893197641101210911874606040804983166177455705972192827752532495287749766682029353154226049380290040508900715169403153139668217790502306177709467234413947747673881158973344492079455405942662489751581189327200960698310350121179918845099840977270519116578719881752429190273998774113278822810866144521416958558406602325070095207349450759264393913367193083149679216066539911941983836313340998945139132421885688290888674594474605510238217590823316979504437667252929278291853368754482552573193289277120902144178425726693671235675042499401282016643202758246845332593475338220708351934511933096882598943512036679145593929114103343255708217768511665236173107020739195152050863630870948954052925049746246549772984384435109578859863612603574306739909728739428192798727373799081111333186135697868385292787575475482883660605162944306327057220313320376280182432763977906971557137715710757099478269250731209785404487629107297262798803645379809868663503452656912571816192881412782623078761411808958183665272686617730596943579533808499348879195167683064937591552734375

Why can Haskell calculate such a large number, and other languages, such as Java, cannot (so easily)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

自我难过 2024-08-05 16:19:53

这是设计理念上的差异

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

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

    Java 的

在每种语言中,您都必须执行一些特殊操作才能获取另一种整数。

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

It's a difference in design philosophy:

  • The designers of Haskell wanted to be sure that users would not be surprised by the seemingly arbitrary failure of an integer computation needing more than 32 bits.

  • The designers of Java wanted to be sure that users would not be surprised by the seemingly arbitrary performance degradation caused by doing lots of computations over integers needing more than 32 bits.

In each language, you have to do something special to get the other kind of integer.

There's a long, honorable history of languages supporting arbitrarily large integers by default. Two of my favorites are Icon and Smalltalk, which are both over 25 years old.

暗地喜欢 2024-08-05 16:19:53

Java 有 BigInteger 类。

它本可以将此功能内置到语言中,但(像许多语言一样)它倾向于使原始功能紧密映射到 CPU 支持的事物上。

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

Java has the BigInteger class.

It could have built this facility into the language, but (like many languages) it tends to make the primitive features map closely onto things that are supported by the CPU.

Haskell on the other hand emphasizes expressiveness in the style of mathematical notation, where "performance" considerations are largely irrelevant.

划一舟意中人 2024-08-05 16:19:53

Haskell 中的数字文字是重载的,因此它们可以表示多种具体类型(例如 IntIntegerFloat 甚至 MyOwnNumber代码>)。

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

x = 4 :: Int
y = 4 :: Integer
z = 4 :: Float

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

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

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

Float 就像 Java float 一样,使用浮点运算。

就像数字文字一样,许多运算符也被重载(使用 类型类),因此可以与不同类型一起使用。 因此,+ 运算符可以与 IntFloat 一起使用。

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

Numeric literals in Haskell are overloaded so that they can represent multiple concrete types (like Int, Integer, Float or even MyOwnNumber).

You can manually chose a specific type by providing type information, like so:

x = 4 :: Int
y = 4 :: Integer
z = 4 :: Float

These three values have different types and operations performed on these will behave differently.

The exact size of an Int is implementation dependent but can be something like 28 bits, this type behaves like a Java primitive int, e.g. it will overflow.

An Integer is a type that can contain arbitrary-precision integers, like the Java BigInteger.

And a Float is like a Java float, using floating point arithmetic.

Just like numeric literals, many operators are also overloaded (using type classes), and can therefor be used with the different types. So the + operator can work with both Ints and Floats.

In your case, since you didn't provide any type information, the interpreter will default to the Integer type. This means that for the ^ operator, it will also choose the Integer instance. Allowing for arbitrary-precision integer calculations.

撕心裂肺的伤痛 2024-08-05 16:19:53

Java 具有“原始数据类型”(处理器支持的类型)的概念,它们与所有其他类不同。

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

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

Java has the notion of "Primitive Data Types" (which are the types that the processor supports) and those are different from all other Classes.

In Haskell, Int is a type like all other types, and therefore it was easily made a member of the Num and Integral typeclasses used in (^) ("(^) :: (Num a, Integral b) => a -> b -> a"). Another member of those typeclasses is Integer, which supports integers of all sizes (as long as you have enough memory for their digits).

In Java, you can use many "Big Numbers" libraries, but the operations for them won't use the infix operators you are used to, because those are only for "Primitive Types" in Java.

無心 2024-08-05 16:19:53

简短而基本的答案是它们实现了不同的默认整数。 在 Java 中,标准 int 是 32 位。 带符号后,您的范围为 −2,147,483,648+2,147,483,647

也就是说,Java 也有 bignum 类。 如果您使用它们,您还将获得使用任意大数字的能力。

The short and basic answer is that they implement default integers differents. In Java, a standard int is 32 bits. Signed, that gives you a range of −2,147,483,648 to +2,147,483,647.

That said, Java has bignum classes too. If you use those, you'll also gain the ability to use arbitrarily large numbers.

在风中等你 2024-08-05 16:19:53

如前所述,如果您有 32 位字并使用完整范围,则使用二进制补码得到 -2^31 到 2^31-1。

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

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

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

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

这些语言的编译器中的许多优化都集中在避免完成这项工作所需的运行时类型检查的开销。 通常还有一些方法可以显式地告诉编译器从 fixnum 到 bignum 的自动降级是不受欢迎的,而是需要 32 位整数的溢出行为。 这对于有效实现密码算法非常重要。

As already mentioned, if you have 32 bit words and use the full range you get -2^31 to 2^31-1 using two's complement.

By reserving a few bits of the word, those bits can be used to carry type-information for the value. That is, values "know" their own type at runtime. The remaining bits are used to carry the value's data.

Integer values that fit in these remaining bits can be stored directly in the word. Such integers are typically called 'fixnums'. If they don't fit, then the type bits of the word indicate it is a 'bigint', and the remaining bits are used to store a memory pointer into the heap where the bigint value is stored.

The compiler needs to translate your arithmetic expressions into multiple code paths that cover allowed type combinations for the operands. Example for addition:

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

A lot of optimizations in compilers for these languages focus on avoiding overhead for the runtime type-checks needed to make this work. There are often also ways to explicitly tell the compiler that automatic demotion from fixnum to bignum is undesired, and instead one want the overflow behavior of 32bit integers. This can be very important for implementing cryptography algorithms efficiently.

少女的英雄梦 2024-08-05 16:19:53

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

It is a matter of how to encode numbers. The traditional way to do this is to encode numbers with a given number of bits, where you cannot have infinite accuracy. Haskell apparently do this with a variable number of bits for a number which is also fine, but usually mean that all math has do be done in software, as hardware acceleration is generally only available for finite accuracy.

南冥有猫 2024-08-05 16:19:53

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

我们拥有如此多语言的原因之一是,不同的语言在不同的任务上表现得更好,因为它们是在不同的假设下设计的。 大多数函数式语言在数学函数方面都比较简单,但在处理其他用例时往往会遇到困难,例如,haskell 不太可能是编写 GUI 的好选择。

You can use BigInteger to do the same thing. Haskell is a functional language which is more terse than Java.

One reason we have so many languages is that different languages are better at different tasks as they were designed with different assumptions. Most functional languages are simpler with mathematical functions but tend to struggle with other use cases e.g. haskell is unlikely to be good choice for writing a GUI.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文