如何处理有限 RAM 设备(任何语言)上的 INT 溢出?
How to handle INT overflow on limited RAM devices (any language)?
我在学校有一个任务,我必须回答这个问题:
"A couple of students make a calendar program where a days "absolute daynumber” 定义为从 0 年 1 月 1 日到今天的天数。在许多小型计算机上,Int 的最大值是 32767。如果我们忽略这个会发生什么? 你如何解决这个问题?
这个问题有点让我困惑。我目前在 Python 工作,根据我的阅读,Python 通过将 Int 转换为 Long 来自动处理 Int 溢出,其他编程语言也做类似的事情(例如环绕到负数,AKA 32768 变为 -32767)。如果编程语言没有自动处理溢出,我想如果数字超过 32767 你会简单地得到一个错误......对吧?
如果你想打印 "absolute daynumber"(假设它超过 32767 并且你只能使用 Int)你将无法打印,因为你不能将值存储在 Int 中。这是不可能的。如果你只想打印今天的日期,你可以从 PC BIOS 中获取它或使用 Unix 时间。
对我来说,这个问题的答案似乎取决于您究竟希望程序做什么。但是我的老师说不行。他说 none 我的答案是正确的。我不太明白他想要什么样的答案,这应该是一个简单的问题,因为我现在只做了大约 2 个月的编程。我错过了什么如此明显?我是不是想多了?
CPU 不会在所有条件下都检测到无效结果,因此您必须自己检查它们。然后你仍然遇到数学不起作用的问题,你不能做你想要的计算。另一种解决方案是将数据存储在更大的数据结构中,并在该结构上实现您自己的 add/subtract/... 操作。
这就是 python 所做的,这就是它可以本地存储不确定大整数的原因。查看 python 的 decimal
模块以获取另一个示例。那里有 C/C++ 的库,我认为还有其他语言。您也可以自己实现一个 API - 它有点乏味但可行。
这并非完全与语言无关,因为正如您所观察到的,有些语言可以处理整数溢出。
而且跟内存无关
它与现代 CPU 架构和整数的工作方式有关。简而言之,CPU 只能使用特定数量的位,称为 "word"。通常,CPU 中处理整数的部分寄存器可以容纳一个字。在您的示例中,单词大小为 16.
也就是说,我们可以存储的最大数(二进制)是:
1111 1111 1111 1111
那么,当我们将其加 1 时会发生什么?
1111 1111 1111 1111
+0000 0000 0000 0001
嗯,1+1 是 10(二进制),所以我们在最后一个位置得到 0,但必须将 1 进位。这导致结果全为 0,加上一个结转的 1。这个1存放在CPU的一个特殊地方,可以被分支指令使用,只要不被后面的算术运算覆盖即可。 (通常,这种所谓的进位不能在编程语言中使用。)
所以我们这里看到的是65535+1的结果是0,貌似不对。
但是我们需要习惯整数运算完成 modulo 2^n 的想法,其中 n 是以位为单位的字长。正确结果是65536,65536mod2^6是0.
我希望你的老师已经告诉你这些基础知识,否则这个问题会显得不公平。
那么,如果你忽视这一点会发生什么?您可能会得到错误的结果。
你怎么解决的?使用两个整数来表示不适合一个整数的数字。如何做到这一点有很多可能性。一种易于理解但在内存效率方面并不理想的可能性是:用 2 个整数表示天数。在第一个整数中,我们只计算千。在第二个中,我们仅表示最后 3 位数字(十进制表示法)。例如,要表示 432105,我们将第一个整数设置为 432,第二个整数设置为 105。
我在学校有一个任务,我必须回答这个问题:
"A couple of students make a calendar program where a days "absolute daynumber” 定义为从 0 年 1 月 1 日到今天的天数。在许多小型计算机上,Int 的最大值是 32767。如果我们忽略这个会发生什么? 你如何解决这个问题?
这个问题有点让我困惑。我目前在 Python 工作,根据我的阅读,Python 通过将 Int 转换为 Long 来自动处理 Int 溢出,其他编程语言也做类似的事情(例如环绕到负数,AKA 32768 变为 -32767)。如果编程语言没有自动处理溢出,我想如果数字超过 32767 你会简单地得到一个错误......对吧?
如果你想打印 "absolute daynumber"(假设它超过 32767 并且你只能使用 Int)你将无法打印,因为你不能将值存储在 Int 中。这是不可能的。如果你只想打印今天的日期,你可以从 PC BIOS 中获取它或使用 Unix 时间。
对我来说,这个问题的答案似乎取决于您究竟希望程序做什么。但是我的老师说不行。他说 none 我的答案是正确的。我不太明白他想要什么样的答案,这应该是一个简单的问题,因为我现在只做了大约 2 个月的编程。我错过了什么如此明显?我是不是想多了?
CPU 不会在所有条件下都检测到无效结果,因此您必须自己检查它们。然后你仍然遇到数学不起作用的问题,你不能做你想要的计算。另一种解决方案是将数据存储在更大的数据结构中,并在该结构上实现您自己的 add/subtract/... 操作。
这就是 python 所做的,这就是它可以本地存储不确定大整数的原因。查看 python 的 decimal
模块以获取另一个示例。那里有 C/C++ 的库,我认为还有其他语言。您也可以自己实现一个 API - 它有点乏味但可行。
这并非完全与语言无关,因为正如您所观察到的,有些语言可以处理整数溢出。
而且跟内存无关
它与现代 CPU 架构和整数的工作方式有关。简而言之,CPU 只能使用特定数量的位,称为 "word"。通常,CPU 中处理整数的部分寄存器可以容纳一个字。在您的示例中,单词大小为 16.
也就是说,我们可以存储的最大数(二进制)是:
1111 1111 1111 1111
那么,当我们将其加 1 时会发生什么?
1111 1111 1111 1111
+0000 0000 0000 0001
嗯,1+1 是 10(二进制),所以我们在最后一个位置得到 0,但必须将 1 进位。这导致结果全为 0,加上一个结转的 1。这个1存放在CPU的一个特殊地方,可以被分支指令使用,只要不被后面的算术运算覆盖即可。 (通常,这种所谓的进位不能在编程语言中使用。)
所以我们这里看到的是65535+1的结果是0,貌似不对。 但是我们需要习惯整数运算完成 modulo 2^n 的想法,其中 n 是以位为单位的字长。正确结果是65536,65536mod2^6是0.
我希望你的老师已经告诉你这些基础知识,否则这个问题会显得不公平。
那么,如果你忽视这一点会发生什么?您可能会得到错误的结果。
你怎么解决的?使用两个整数来表示不适合一个整数的数字。如何做到这一点有很多可能性。一种易于理解但在内存效率方面并不理想的可能性是:用 2 个整数表示天数。在第一个整数中,我们只计算千。在第二个中,我们仅表示最后 3 位数字(十进制表示法)。例如,要表示 432105,我们将第一个整数设置为 432,第二个整数设置为 105。