用有符号长整型结果减去无符号长整型
Subtracting unsigned long longs with signed long long result?
假设我有这两种类型:
typedef unsigned long long uint64;
typedef signed long long sint64;
我有这些变量:
uint64 a = ...;
uint64 b = ...;
sint64 c;
我想从a中减去b,并将结果分配给c,很明显,如果差值的绝对值大于2^63,它将被包裹(或未定义),这是可以的。但对于绝对差值小于2^63的情况,我希望结果是正确的。
以下三种方式之一:
c = a - b; // sign conversion warning ignored
c = sint64(a - b);
c = sint64(a) - sint64(b);
他们中的哪一个能保证按标准工作?(为什么/如何?)
这三种方法都不起作用。如果差值为负(无论绝对值如何),则第一个会失败,第二个与第一个相同,如果任一操作数过大,则第三个会失败。
没有分支是不可能实现的。
c = b < a? a - b : - static_cast< sint64 >( b - a );
从根本上讲,unsigned
类型使用无任何符号位的模运算。他们不知道自己被包装了,语言规范也没有用负数来识别包装。此外,赋值在有符号积分变量范围之外会导致实现定义的潜在无意义结果(积分溢出)。
考虑一台没有硬件在本机负整数和2的补码之间转换的机器。不过,它可以使用逐位否定和原生二的补码相加来执行二的补数相减。(也许很奇怪,但这正是C和C++目前所需要的。)然后,该语言将负值的转换留给程序员。唯一的方法是否定一个正值,这需要计算出的差值为正。所以…
最好的解决方案是首先避免将负数表示为大正数。
EDIT:我之前忘记了强制转换,它会产生一个大的无符号值,与其他解决方案等效!
Potatoswatter的答案可能是最实用的解决方案,但"没有分支就不可能实现"对我来说就像一块红抹布。如果你的假设系统实现了这样未定义的溢出/强制执行操作,my假设系统通过杀死小狗来实现分支。
所以我不完全熟悉标准会说什么,但这个怎么样:
sint64 c,d,r;
c = a >> 1;
d = b >> 1;
r = (c-d) * 2;
c = a & 1;
d = b & 1;
r += c - d;
我用一种相当详细的方式编写了它,因此各个操作都很清楚,但留下了一些隐式的强制转换。有什么东西没有定义?
Steve Jessop正确地指出,在差值正好为2^63-1的情况下,这确实失败了,因为在减去1之前乘法溢出。
因此,这里有一个更丑陋的版本,它应该涵盖所有下溢/上溢条件:
sint64 c,d,r,ov;
c = a >> 1;
d = b >> 1;
ov = a >> 63;
r = (c-d-ov) * 2;
c = a & 1;
d = b & 1;
r += ov + ov + c - d;
如果差值的绝对值大于2^63将包装(或未定义),这是可以的。但对于绝对差值小于2^63我希望结果是正确的。
然后,假设采用传统架构,您建议的所有三种符号都有效。显著差异第三个sint64(a) - sint64(b)
调用未定义的行为当差异不可表示时,而前两者是保证环绕(无符号算术溢出保证环绕,从无符号到有符号的转换是实现定义的,而有符号算术溢出是未定义的)。
- 无法在 Arduino 中uint8_t数组转换为无符号长整型数组
- 提升不良词法强制转换:将字符串转换为无符号长整型时,无法将源类型值解释为目标
- 将最小值整数转换为无符号长整型
- 如何将小端格式的QByteArray转换为无符号长整型
- 无符号长整型和无符号 int 之间有什么区别,这 2 种类型应该如何在 c# 中封送?
- 如何以优雅高效的方式将无符号/有符号整数/长整型转换为 C 字符串?
- 将 BYTE 数组转换为无符号长整型
- 整数溢出 C++ 即使使用“无符号长整型”也是如此
- gdb ptype 打印整数后缀以指示它是有符号的、无符号的、无符号的长整型等
- 模板参数可以既是 int 又可以是无符号长整型吗?
- 用有符号长整型结果减去无符号长整型
- iOS - 隐式转换将整数精度"size_t"(也称为"无符号长整型")丢失为&
- 将字符串存储在无符号长整型的向量中
- 如果我尝试在 c++ 中将大于 pow(2,64)-1 的值分配给无符号长整型怎么办?
- C++:将无符号长整型长整型转换为无符号长整型
- 在 CORBA 客户端/服务器应用程序中将无符号的长整型(从 C++)断言为长整型 (Java)
- 无法将DWORD转换为无符号长整型
- 无符号长整型VS无符号长型整型
- 如何将SHA1转换为无符号长整型数组[5]
- 如何将 3 个整数连接成无符号长整型