我查看了与Big Integer有关的stackoverflow问题,特别是我不理解这一行(斜体字):
在BigInteger类中,我没有限制,并且有一些有用的函数,但将你漂亮的代码转换为使用BigInteger类非常令人沮丧,特别是当原始操作符不能在那里工作时你必须使用这个类中的函数.
我不知道我错过了什么,但代表一些没有限制的东西,你需要无限的记忆?这是什么诀窍?
在C#中,我看到了
-1 * int.MinValue == int.MinValue
Run Code Online (Sandbox Code Playgroud)
这是一个错误吗?当我试图实现搜索树时,它真的搞砸了我.我最终使用,(int.MinValue + 1)所以我可以正确否定它.
我最近读到C和C++中的带符号整数溢出会导致未定义的行为:
如果在评估表达式期间,结果未在数学上定义或未在其类型的可表示值范围内,则行为未定义.
我目前正试图了解这里未定义行为的原因.我认为这里发生了未定义的行为,因为当整数变得太大而无法适应底层类型时,整数开始操纵自身周围的内存.
所以我决定在Visual Studio 2015中编写一个小测试程序,用以下代码测试该理论:
#include <stdio.h>
#include <limits.h>
struct TestStruct
{
char pad1[50];
int testVal;
char pad2[50];
};
int main()
{
TestStruct test;
memset(&test, 0, sizeof(test));
for (test.testVal = 0; ; test.testVal++)
{
if (test.testVal == INT_MAX)
printf("Overflowing\r\n");
}
return 0;
}
Run Code Online (Sandbox Code Playgroud)
我在这里使用了一个结构来防止Visual Studio在调试模式下的任何保护问题,比如堆栈变量的临时填充等等.无限循环应该导致几次溢出test.testVal,确实如此,除了溢出本身之外没有任何后果.
我在运行溢出测试时查看了内存转储,结果如下(test.testVal内存地址为0x001CFAFC):
0x001CFAE5 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
0x001CFAFC 94 53 …Run Code Online (Sandbox Code Playgroud) 在几种现代编程语言(包括C++,Java和C#)中,该语言允许在运行时发生整数溢出,而不会引发任何类型的错误条件.
例如,考虑这个(人为的)C#方法,它没有考虑上溢/下溢的可能性.(为简洁起见,该方法也不处理指定列表为空引用的情况.)
//Returns the sum of the values in the specified list.
private static int sumList(List<int> list)
{
int sum = 0;
foreach (int listItem in list)
{
sum += listItem;
}
return sum;
}
Run Code Online (Sandbox Code Playgroud)
如果调用此方法如下:
List<int> list = new List<int>();
list.Add(2000000000);
list.Add(2000000000);
int sum = sumList(list);
Run Code Online (Sandbox Code Playgroud)
sumList()方法中将发生溢出(因为intC#中的类型是32位有符号整数,并且列表中值的总和超过了最大32位有符号整数的值).sum变量的值为-294967296(不是值4000000000); 这很可能不是sumList方法的(假设的)开发人员所期望的.
显然,开发人员可以使用各种技术来避免整数溢出的可能性,例如使用类似Java的类型BigInteger,或者使用C#中的checked关键字和/checked编译器开关.
但是,我感兴趣的问题是为什么这些语言默认设计为允许整数溢出首先发生,而不是例如在运行时执行操作时引发异常,从而导致溢出.看起来这种行为有助于避免在编写执行可能导致溢出的算术运算的代码时开发人员忽略解释溢出可能性的情况下的错误.(这些语言可能包含类似"未经检查"的关键字,它可以指定允许发生整数溢出而不会引发异常的块,在开发人员明确意图该行为的情况下; C#实际上确实有这个. )
答案简单归结为性能 - 语言设计者不希望他们各自的语言默认具有"慢"算术整数运算,其中运行时需要做额外的工作来检查是否发生溢出,在每个适用的算术上操作 - 这种性能考虑超过了在无意溢出发生时避免"无声"故障的价值?
除了性能考虑之外,还有其他原因可以做出这种语言设计决策吗?
C标准明确规定有符号整数溢出具有未定义的行为。然而,大多数CPU都使用定义的语义为溢出实现签名算法(可能除法除法溢出为:x / 0和INT_MIN / -1)。
编译器的作家一直在走的优势undefinedness这种溢出的补充,往往会打破传统的代码非常微妙的方式更积极的优化。例如,此代码可能在较旧的编译器上有效,但在gccand的当前版本上不再有效clang:
/* Tncrement a by a value in 0..255, clamp a to positive integers.
The code relies on 32-bit wrap-around, but the C Standard makes
signed integer overflow undefined behavior, so sum_max can now
return values less than a. There are Standard compliant ways to
implement this, but legacy code is what it is... */
int sum_max(int a, unsigned char b) {
int …Run Code Online (Sandbox Code Playgroud) 我有以下代码,当完整的二进制树是layer图层高时,它返回树中的节点数:
public static long nNodesUpToLayer(int layer) {
if (layer < 0) throw new IllegalArgumentException(
"The layer number must be positive: " + layer );
//At layer 0, there must be 1 node; the root.
if (layer == 0) return 1;
//Else, there will be 1 + 2 * (the number of nodes in the previous layer) nodes.
return 1 + (2 * nNodesUpToLayer(layer - 1));
Run Code Online (Sandbox Code Playgroud)
奇怪的是,当我输入63函数(产生这个的最小值)时,它会让我回来-1.在62,它回馈9223372036854775807,所以这似乎是由溢出引起的.
它不应该让我回到Java长期的最小值+它溢出的数量吗?无论我给它(通过62)的输入如何,它总是会返回-1 …
有(1):
// assume x,y are non-negative
if(x > max - y) error;
Run Code Online (Sandbox Code Playgroud)
并且(2):
// assume x,y are non-negative
int sum = x + y;
if(sum < x || sum < y) error;
Run Code Online (Sandbox Code Playgroud)
哪个是首选或有更好的方法.
System.out.println(Integer.MAX_VALUE + 1 == Integer.MIN_VALUE);
是真的.
我知道Java中的整数是32位,不能超过2 ^ 31-1,但我不明白为什么在MAX_VALUE中加1会导致MIN_VALUE而不是某种异常.没有像Ruby那样透明地转换为更大的类型.
是否在某处指定了此行为?我可以依靠它吗?
通过"非空",我的意思是在这个问题中包含至少一个非零字符的字符串.
作为参考,这是hashCode实现:
1493 public int hashCode() {
1494 int h = hash;
1495 if (h == 0) {
1496 int off = offset;
1497 char val[] = value;
1498 int len = count;
1499
1500 for (int i = 0; i < len; i++) {
1501 h = 31*h + val[off++];
1502 }
1503 hash = h;
1504 }
1505 return h;
1506 }
Run Code Online (Sandbox Code Playgroud)
并且算法在文档中指定.
在发生整数溢出之前,答案很简单:它不是.但我想知道的是,由于整数溢出,非空字符串的哈希码是否可能为零?你能建一个吗?
我正在寻找的理想情况是数学演示(或链接到一个)或构造算法.
以下结果让我很困惑:
int i1 = 20-80u; // -60
int i2 = 20-80; // -60
int i3 =(20-80u)/2; // 2147483618
int i4 =(20-80)/2; // -30
int i5 =i1/2; // -30
Run Code Online (Sandbox Code Playgroud)
i3似乎计算为(20u-80u)/2,而不是(20-80u)/2i3是一样的i5.