标签: integer-overflow

如何在 C# 中检查 Interlocked.Increment 后是否溢出?

调用后检查溢出的正确方法是什么Interlocked.Increment

我有一个 ID 生成器,可以在程序执行期间生成唯一的 ID,目前我测试增量是否返回零。

public static class IdGenerator {
    private static int _counter = 0;
    
    public static uint GetNewId() {
        uint newId = (uint)System.Threading.Interlocked.Increment(ref _counter);
        if (newId == 0) {
             throw new System.Exception("Whoops, ran out of identifiers");
        }
        return newId;
    }
}
Run Code Online (Sandbox Code Playgroud)

鉴于我每次运行生成的 ID 数量相当大,(在异常大的输入上)_counter增量时可能会溢出,并且我想在这种情况下抛出异常(尽早崩溃以简化调试)。

摘自微软的文档

location此方法通过包装: if = Int32.MaxValue, location + 1=来处理溢出情况Int32.MinValue。没有抛出异常。

c# integer-overflow interlocked interlocked-increment

2
推荐指数
1
解决办法
2977
查看次数

c 中整数的环绕

我已经用 c 编程有一段时间了。但从未使用过发生整数环绕的程序。我知道如果整数分配了4个字节,那么整数的范围就变成-2,147,483,648到2,147,483,647。如果我们超过了限制,它就会绕回。

我正在使用以下程序来了解环绕是如何发生的。

#include <stdio.h>

int main() {
int n = 4, s = 2;

for (int i = 0; i < n; ++i)
{
    for (int j = 0; j < n; ++j)
    {
        for (int k = 0; k < n; ++k)
        {
            s = 2 * s + 1;

        }
    }
}
printf("%d\n", s);
return 0;
}
Run Code Online (Sandbox Code Playgroud)

我正在使用 gdb 来找出变量 s 所取的值。我发现当我们执行最里面的循环第30次时,s的值变成负数,即-1073741825。然后,对于下一次迭代,它变为 2147483647,对于第 32 次迭代,它变为 -1。gdb 的快照

然后它永远保持为-1。我的疑问是为什么值变为-1后没有发生回绕。我知道二进制中 s 的值将全为 1 或十六进制中的 FFFFFFFF 。而且它不会永远改变(它在内部更新,但我们只能看到最后 32 位,所以它是 -1)。但是这次环绕没有出现吗?它依赖于编译器吗?或者 …

c integer-overflow

2
推荐指数
1
解决办法
6447
查看次数

Tensorflow 中的 log(1+exp(X))(避免欠流和过流)

我正在调试我的程序,我意识到我的损失输出了 NaN。这些 NaN 值来自我正在计算的事实tf.log(1 + tf.exp(X))

其中 X 是一个二维张量。实际上,当 X 的值足够大时, tf.exp() 返回 +Inf ,因此tf.log(1 + exp(X))将返回+Inf。我想知道在这种情况下是否存在避免下溢和溢出的巧妙技巧。

我试过了:

def log1exp(x):
    maxi = tf.reduce_max(x)
    return maxi + tf.log(tf.exp(x - maxi) + tf.exp(-maxi))
Run Code Online (Sandbox Code Playgroud)

但在这种情况下它不处理下溢......

我也看了一眼,tf.reduce_logsumexp但它必然会减少沿轴的张量......而我想保持相同的形状!

最后我知道这tf.log(1 + exp(X))几乎等于XX 的大值,但我认为设计一个将输出XwhenX > threshold和 log(1+exp(X)) 否则不是很整洁的函数。

谢谢

integer-overflow nan exp tensorflow

2
推荐指数
1
解决办法
1512
查看次数

隐式转换双精度到无符号长溢出C++

我正在使用 Clock() 函数测试基于 ctime 库的计时器。请注意,下面的代码仅用于测试目的。

#include <ctime>

unsigned long Elapsed(void);

clock_t start = 0;
clock_t stop = 0;

int main()
{
  start = std::clock();
  while(1)
   {
    sleep(1);
    cout << "Elapsed seconds: " << Elapsed() << endl;
   }
return 0;
}

unsigned long Elapsed()
{
  stop = std::clock();
  clock_t ticks = stop - start;
  double seconds = (double)ticks / CLOCKS_PER_SEC;  //CLOCK_PER_SEC = 1 milion
  return seconds;
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,当 Elapsed() 返回计算值时,我正在执行从 double 到 unsigned long 的隐式转换。32 位系统的无符号长限制是 2,147,483,647,并且在 Elapsed() 返回 2146 后出现溢出。 …

c++ integer-overflow ctime

2
推荐指数
1
解决办法
708
查看次数

Rust 溢出时带边界的整数运算

我最近遇到的问题需要根据整数类型的位进行带边界的整数运算。

例如,使用i32整数进行add运算,这里有一段伪代码来表达这个想法:

sum = a + b
max(min(sum, 2147483647), -2147483648)

// if the sum is larger than 2147483647, then return 2147483647.
// if the sum is smaller than -2147483648, then return -2147483648.
Run Code Online (Sandbox Code Playgroud)

为了实现这一点,我天真地写了以下丑陋的代码:

sum = a + b
max(min(sum, 2147483647), -2147483648)

// if the sum is larger than 2147483647, then return 2147483647.
// if the sum is smaller than -2147483648, then return -2147483648.
Run Code Online (Sandbox Code Playgroud)

代码运行良好;但是我的六感告诉我使用类型转换是有问题的。因此,我尝试使用传统的恐慌(异常)处理来解决这个问题……但我坚持使用下面的代码(恐慌结果无法检测下溢或溢出):

fn i32_add_handling_by_casting(a: i32, b: i32) -> i32 {
    let sum: …
Run Code Online (Sandbox Code Playgroud)

integer-overflow panic rust

2
推荐指数
1
解决办法
488
查看次数

为什么“INT_MAX * INT_MAX”乘积给出 1?

我正在学习计算机体系结构,并决定尝试乘法溢出。观察到 的溢出INT_MAX * INT_MAX,但我不确定为什么这会在 C/C++ 中给出乘积 1。

#include <stdio.h>
#include <limits.h>

int main()
{
    int num = INT_MAX;
    printf("%0x\n", num);       //stdout is 0x7fffffff
    printf("%d\n", num * num);  //stdout is 1
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

c integer-overflow cpu-architecture

2
推荐指数
1
解决办法
282
查看次数

删除常量表达式中带符号整数溢出的未定义行为?

编辑在实际示例中,似乎可能会发生负溢出,我还添加了一个示例来演示那里的错误

我正在使用 C++20 并尝试将依赖于 Java 和 C# 中的有符号整数溢出的库转换为 C++ 代码。我还尝试生成它在编译时使用的表,并允许它们在编译时可用。

在我的代码中,我在引用看起来像这样的代码时遇到错误(重现错误的最小示例,该解决方案也将解决我的问题):

#include <iostream> 

constexpr auto foo(){
    std::int64_t a = 2; 
    std::int64_t very_large_constant = 0x598CD327003817B5L; 
    std::int64_t x = a * very_large_constant; 
    return x; 
}
 
int main(){
    std::cout << foo() << std::endl; 
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/TvM45vd8d

负溢出版本

#include <iostream> 

constexpr auto foo(){
    std::int64_t a = -2; 
    std::int64_t very_large_constant = 0x598CD327003817B5L; 
    std::int64_t x = a * very_large_constant; 
    return x; 
}
 
int main(){
    std::cout << foo() << std::endl; 
    return 0; 
}
Run Code Online (Sandbox Code Playgroud)

https://godbolt.org/z/7zoE9r18E

我得到 12905529061151879018 …

c++ integer-overflow undefined-behavior constexpr c++20

2
推荐指数
2
解决办法
225
查看次数

当循环变量在溢出时未定义时,可以进行哪些优化?

本文提供了一个 C 代码示例片段,由于循环计数器类型未定义溢出,因此编译器可以对其进行优化。

这是带有评论的片段

for (i = 0; i <= N; ++i) { ... }
Run Code Online (Sandbox Code Playgroud)

在此循环中,如果“i”在溢出时未定义,编译器可以假设循环将精确迭代 N+1 次,这允许进行广泛的循环优化。另一方面,如果变量定义为溢出时回绕,那么编译器必须假设循环可能是无限的(如果 N 为 INT_MAX,就会发生这种情况)——然后禁用这些重要的循环优化。这尤其影响 64 位平台,因为大量代码使用“int”作为归纳变量。

我有不少疑问:

  • 我知道,如果 的类型i在溢出时未定义,编译器可以假设i不会回绕,但是为什么这意味着循环运行了N+1多次?不能i在循环体中改变它吗?
  • 即使考虑到这一假设,它还能基于此进行哪些优化?例如,如果N在编译时未知,则无法展开循环,不是吗?
  • “广泛的循环优化”让我觉得我在这里错过了很多。

c integer-overflow compiler-optimization undefined-behavior

2
推荐指数
1
解决办法
176
查看次数

C#中++运算符的一致行为

++应用于C#中的long的应用程序的行为在应用时是否一致long.MaxValue?呼叫不是在一个checked块内进行的.我需要知道,无论在任何情况下,现在还是将来,它都可能抛出OverflowException而不是包装long.MinValue.

c# increment integer-overflow

1
推荐指数
1
解决办法
135
查看次数

数组索引上的整数溢出

我在32位架构上使用C语言.

如果我使用array[-2147483635]为什么C将其转换为array[13]

-2147483635 在Two的补充是 10000000000000000000000000001101b

是否需要左位并将其转换为0以便它变为 00000000000000000000000000001101b,即13???

我认为它不适合size_t.因为size_t翻译-21474836354294967264.

c integer-overflow

1
推荐指数
1
解决办法
580
查看次数