编程语言如何处理大数运算
对于使用 64 位处理器的计算机,它可以处理的最大数字为 264 = 18,446,744,073,709,551,616。编程语言(例如 Java 或者 C、C++)如何处理高于该值的数字的算术。任何寄存器都不能将其作为一个整体保存。这个问题是如何解决的?
For a computer working with a 64 bit processor, the largest number that it can handle would be 264 = 18,446,744,073,709,551,616. How does programming languages, say Java or be it C, C++ handle arithmetic of numbers higher than this value. Any register cannot hold it as a single piece. How was this issue tackled?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(9)
有许多专门的技术可以对大于寄存器大小的数字进行计算。其中一些在关于任意精度算术
低级语言(例如 C)的 维基百科文章中进行了概述和 C++,将大量计算留给您选择的库。值得注意的一个是 GNU 多精度库。 Python 等高级语言将其集成到语言的核心中,因此普通数字和非常大的数字对于程序员来说是相同的。
There are lots of specialized techniques for doing calculations on numbers larger than the register size. Some of them are outlined in this wikipedia article on arbitrary precision arithmetic
Low level languages, like C and C++, leave large number calculations to the library of your choice. One notable one is the GNU Multi-Precision library. High level languages like Python, and others, integrate this into the core of the language, so normal numbers and very large numbers are identical to the programmer.
处理真正海量数字的编程语言使用自定义数字原语,这些原语超出了针对 32、64 或 128 位 CPU 优化的正常操作。这些数字在计算机安全和数学研究中特别有用。
GNU 多精度库可能是这些方法中最完整的示例。
您可以使用数组来处理更大的数字。在网络浏览器中尝试一下。在网络浏览器的 JavaScript 控制台中键入以下代码:
JavaScript 失败的点
JavaScript 不处理
9999999999999998
以上的纯整数。但是编写自己的数字原语是为了让这个计算工作足够简单。以下是使用 JavaScript 中的自定义数字加法器类 的示例。使用自定义数字类通过测试
工作原理
您可以在以下位置查看代码:class Num { ... } 查看正在发生的详细信息;但这里是所使用逻辑的基本概述:
类:
Num
类包含单个Digit
类的数组。Digit
类包含单个数字的值,以及处理Carry 标志
的逻辑步骤:
Num
类中。Num
递增时,它会被传送到第一个Digit<数组中的 /code>(最右边的数字)
Digit
值加上Carry 标志
等于Base
,则左边的下一个Digit
被调用递增,当前数字重置为0
...逻辑上 它与机器级别发生的情况非常相似,但这里它是无限的。您可以阅读有关数字的更多信息
此处携带;这可以应用于任何基数的数字。
Programming languages that handle truly massive numbers use custom number primitives that go beyond normal operations optimized for 32, 64, or 128 bit CPUs. These numbers are especially useful in computer security and mathematical research.
The GNU Multiple Precision Library is probably the most complete example of these approaches.
You can handle larger numbers by using arrays. Try this out in your web browser. Type the following code in the JavaScript console of your web browser:
The point at which JavaScript fails
JavaScript does not handle plain integers above
9999999999999998
. But writing your own number primitive is to make this calculation work is simple enough. Here is an example using a custom number adder class in JavaScript.Passing the test using a custom number class
How it Works
You can look in the code at class Num { ... } to see details of what is happening; but here is a basic outline of the logic in use:
Classes:
Num
class contains an array of singleDigit
classes.Digit
class contains the value of a single digit, and the logic to handle theCarry flag
Steps:
Digit
class and stored in theNum
class as an array of digitsNum
is incremented, it gets carried to the firstDigit
in the array (the right-most number)Digit
value plus theCarry flag
are equal to theBase
, then the nextDigit
to the left is called to be incremented, and the current number is reset to0
Logistically it is very similar to what is happening at the machine level, but here it is unbounded. You can read more about about how digits are
carried here; this can be applied to numbers of any base.
你假设了错误的事情。它在单个寄存器中可以处理的最大数字是 64 位数字。然而,通过一些智能编程技术,您可以将几十个 64 位数字连续组合起来,生成一个巨大的 6400 位数字,并用它来进行更多计算。它只是不如将数字放入一个寄存器那么快。
即使是旧的 8 位和 16 位处理器也使用了这个技巧,它们只是让数字溢出到其他寄存器。它使数学变得更加复杂,但并没有消除可能性。
然而,如此高精度的数学是极其不寻常的。我认为,即使您想计算美国的全部国债并将结果存储为津巴布韦元,64 位整数仍然足够大。不过,它绝对足够容纳我的储蓄账户的金额。
You assume the wrong thing. The biggest number it can handle in a single register is a 64-bits number. However, with some smart programming techniques, you could just combined a few dozens of those 64-bits numbers in a row to generate a huge 6400 bit number and use that to do more calculations. It's just not as fast as having the number fit in one register.
Even the old 8 and 16 bits processors used this trick, where they would just let the number overflow to other registers. It makes the math more complex but it doesn't put an end to the possibilities.
However, such high-precision math is extremely unusual. Even if you want to calculate the whole national debt of the USA and store the outcome in Zimbabwean Dollars, a 64-bits integer would still be big enough, I think. It's definitely big enough to contain the amount of my savings account, though.
或多或少与您的做法相同。在学校里,你记住了个位数的加法、乘法、减法和除法。然后,您学习了如何将多位数问题作为一系列单位数问题来解决。
如果您愿意,您只需使用简单算法的知识和单位数乘法表即可将两个二十位数字相乘。
More-or-less the same way that you do. In school, you memorized single-digit addition, multiplication, subtraction, and division. Then, you learned how to do multiple-digit problems as a sequence of single-digit problems.
If you wanted to, you could multiply two twenty-digit numbers together using nothing more than knowledge of a simple algorithm, and the single-digit times tables.
Ada 实际上本身就支持这一点,但仅限于其无类型常量(“命名数字”)。对于实际的变量,你需要去找一个任意长度的包。请参阅 Ada 中的任意长度整数
Ada actually supports this natively, but only for its typeless constants ("named numbers"). For actual variables, you need to go find an arbitrary-length package. See Arbitrary length integer in Ada
一般来说,语言本身并不能处理高精度、高精度的大数运算。更有可能编写一个使用替代数值方法来执行所需操作的库。
例如(我现在正在编造这个),这样的库可能会模拟您可能用来手动执行大量算术的实际技术。此类库通常比使用内置算术慢得多,但有时需要额外的精度和准确度。
In general, the language itself doesn't handle high-precision, high-accuracy large number arithmetic. It's far more likely that a library is written that uses alternate numerical methods to perform the desired operations.
For example (I'm just making this up right now), such a library might emulate the actual techniques that you might use to perform that large number arithmetic by hand. Such libraries are generally much slower than using the built-in arithmetic, but occasionally the additional precision and accuracy is called for.
作为一个思想实验,想象一下数字存储为字符串。具有对这些任意长的数字进行加法、乘法等功能。
实际上,这些数字可能以更节省空间的方式存储。
As a thought experiment, imagine the numbers stored as a string. With functions to add, multiply, etc these arbitrarily long numbers.
In reality these numbers are probably stored in a more space efficient manner.
将一个机器大小的数字视为一位数字,并应用小学中的多位数乘法算法。然后,您不需要将整个数字保存在寄存器中,只需保存处理后的数字即可。
Think of one machine-size number as a digit and apply the algorithm for multi-digit multiplication from primary school. Then you don't need to keep the whole numbers in registers, just the digits as they are worked on.
大多数语言将它们存储为整数数组。如果您对这些大数中的两个进行加/减,则库会分别对数组中的所有整数元素进行加/减,并处理进位/借位。
这就像学校里的手动加法/减法,因为这就是它内部的工作原理。
有些语言使用真实的文本字符串而不是整数数组,虽然效率较低,但更容易转换为文本表示形式。
Most languages store them as array of integers. If you add/subtract two to of these big numbers the library adds/subtracts all integer elements in the array separately and handles the carries/borrows.
It's like manual addition/subtraction in school because this is how it works internally.
Some languages use real text strings instead of integer arrays which is less efficient but simpler to transform into text representation.