调用后检查溢出的正确方法是什么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 编程有一段时间了。但从未使用过发生整数环绕的程序。我知道如果整数分配了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。
然后它永远保持为-1。我的疑问是为什么值变为-1后没有发生回绕。我知道二进制中 s 的值将全为 1 或十六进制中的 FFFFFFFF 。而且它不会永远改变(它在内部更新,但我们只能看到最后 32 位,所以它是 -1)。但是这次环绕没有出现吗?它依赖于编译器吗?或者 …
我正在调试我的程序,我意识到我的损失输出了 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)) 否则不是很整洁的函数。
谢谢
我正在使用 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 后出现溢出。 …
我最近遇到的问题需要根据整数类型的位进行带边界的整数运算。
例如,使用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) 我正在学习计算机体系结构,并决定尝试乘法溢出。观察到 的溢出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++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 代码示例片段,由于循环计数器类型未定义溢出,因此编译器可以对其进行优化。
这是带有评论的片段
Run Code Online (Sandbox Code Playgroud)for (i = 0; i <= N; ++i) { ... }在此循环中,如果“i”在溢出时未定义,编译器可以假设循环将精确迭代 N+1 次,这允许进行广泛的循环优化。另一方面,如果变量定义为溢出时回绕,那么编译器必须假设循环可能是无限的(如果 N 为 INT_MAX,就会发生这种情况)——然后禁用这些重要的循环优化。这尤其影响 64 位平台,因为大量代码使用“int”作为归纳变量。
我有不少疑问:
i在溢出时未定义,编译器可以假设i不会回绕,但是为什么这意味着循环运行了N+1多次?不能i在循环体中改变它吗?N在编译时未知,则无法展开循环,不是吗?++应用于C#中的long的应用程序的行为在应用时是否一致long.MaxValue?呼叫不是在一个checked块内进行的.我需要知道,无论在任何情况下,现在还是将来,它都可能抛出OverflowException而不是包装long.MinValue.
我在32位架构上使用C语言.
如果我使用array[-2147483635]为什么C将其转换为array[13]?
-2147483635 在Two的补充是 10000000000000000000000000001101b
是否需要左位并将其转换为0以便它变为
00000000000000000000000000001101b,即13???
我认为它不适合size_t.因为size_t翻译-2147483635成4294967264.
integer-overflow ×10
c ×4
c# ×2
c++ ×2
c++20 ×1
constexpr ×1
ctime ×1
exp ×1
increment ×1
interlocked ×1
nan ×1
panic ×1
rust ×1
tensorflow ×1