0

这是一个两部分的问题。

  1. 我有一个添加数字的小代码;然而,这些数字的增长速度往往快于long long所能容纳的速度。

    所以我想我会开一堂课把它移过来。

    我的思考过程给出了 3 long long a, b, c;,

    将所有内容添加到容量c时,添加一并设置为零;一次是“满的”加一并将和设置为零,依此类推。cbcbabc

    c所以,在我重置它并添加一个之前,我必须检查它是否处于容量b状态,依此类推!

    有没有办法检查?

  2. 有人可以指出我制作自己的数据类型的正确方向吗?从视觉上看,我将 3 long longs 像上面一样放在一起,数据类型将完成我上面所说的。

最后,我想像对待整数一样对待我的新数据类型:

整数a = 0;

我希望能够做到

我的数据类型 a = 0;

英语不是我的第一语言。

4

3 回答 3

2

标题<limits.h>定义,除其他外:

  • LLONG_MAX— 可以存储在 (signed) 中的最大值long long。它的最小可接受值为 +9223372036854775807 (2 63 -1)。
  • ULLONG_MAX— 可以存储在 中的最大值unsigned long long。它的最小可接受值为 18446744073709551615 (2 64 -1)。

您可以通过将它们与其中一个适当的值进行比较来测试您的数字是否已达到这些限制。

于 2012-11-11T05:48:52.943 回答
2

测试一个整数是否在容量范围内意味着您的代码将非常低效。例如,要添加 123,您需要进行 123 次增量和 123 次比较。

更好的方法是在执行操作之前确定操作是否会溢出。例如(仅适用于无符号整数):

if(sum <= ULLONG_MAX - a) {
    sum += a;
} else {
    /* It would have overflowed */
}

这是有效的,因为ULLONG_MAX - a不能溢出。当您开始查看有符号整数时,它会成为一个更大的问题,因为它LLONG_MAX - a可能会溢出(如果a为负数),也LLONG_MIN - a可能会溢出(如果a为正数)。您需要测试两种方式:

if( ( a > 0) && (sum <= LLONG_MAX - a) {
    sum += a;
} else if( ( a < 0) && (sum >= LLONG_MIN - a) {
    sum += a;
} else if( a != 0) {
    /* It would have overflowed */
}

一旦确定它是否会溢出,您就需要处理这种情况。例如; 如果您使用多个整数来表示一个更大的整数;然后(对于无符号整数):

if(sum_low <= ULLONG_MAX - a) {
    sum_low += a;
} else {
    sum_low -= (ULLONG_MAX - a) + 1;
    sum_high++;
}

请注意,您必须非常小心,以避免在处理原始(避免)溢出时涉及的临时计算中发生意外溢出。

如果使用多个有符号整数来表示一个较大的有符号整数,那么溢出处理背后的逻辑就会变得复杂且容易出错。理论上是可以的;但是,最好将数字的符号分开,然后单独对无符号整数进行运算(或其逆运算-例如减去正数而不是添加负数);特别是如果您需要使用 3 个或更多整数来表示一个大整数,或者如果您需要更复杂的操作,例如乘法和除法。

当然,一旦您开始走这条路,您就可以有效地实现自己的“大数字”代码,并且可能应该找到/使用合适的库。

最后,如果您想将新数据类型视为原始数据类型(例如,并且能够执行类似的操作mydatatype a = 0;),那么您就不走运了——C 不能以这种方式工作。从本质上讲,C 是美丽的,因为它不允许对试图阅读/理解代码的人隐藏复杂的事物;如果你想向毫无戒心的受害者隐藏重要信息,你就必须使用像 C++ 这样不那么漂亮的语言。;-)

于 2012-11-11T07:44:15.917 回答
1

如果您在谈论签名数字,您可以通过执行以下操作来判断数字是否处于“容量”状态:

if (c > 0 && c + x < 0)

对于无符号数字,它会是类似的:

if (c + x < c)

在这两种情况下,您只需检查溢出。之后,如果有溢出,那么你将加 1b并将余数 ( MAX_LONG_LONG - c) 放回c. 以此类推,从b到的过渡a

add如果不创建自己的结构并编写以及subtract围绕这些结构的函数,我想不出一种简单的方法来做到这一点。

于 2012-11-11T05:37:00.320 回答