我试图在执行算术运算之前将算术运算限制为最多 32 位整数的结果,特别是用于加法。
此循环将找到位位置:
size_t highestOneBitPosition(uint32_t a) {
size_t bits=0;
while (a!=0) {
++bits;
a>>=1;
};
return bits;
}
此函数有效地限制乘法:
bool multiplication_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits+b_bits<=32);
}
但是,我不确定如何通过添加来做到这一点。像这样:
bool addition_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits<32 && b_bits<32);
}
但是,这不会将整数限制为 32 位(或有符号的 0x7FFFFFFF(。它将确保每个操作数都有那么多位位置。
从数学上讲,如果将两个数字相加,则最多有 1 进入最长位置。因此,如果您在 3 位数字(或任何 4 位或更少的数字(中添加一个 4 位数字,则最多有一个 5 位数字。除了,当你有两个相同的时,你最终可以得到更多(99 * 99 = 9801(,所以它将与乘法(a_bits+b_bits <=32(的概念相同
我要做的就是确定最长的操作数,然后加 1 并确保它不超过 32 位位置。我完全不确定如何使用函数来做到这一点。我的问题是我如何修改 addition_is_safe(uint32_t a、uint32_t b( 以将结果限制为 <=32,因为它在 multiplication_is_safe 中。我绝对想利用这个最高的一个位位置。
首先,我什至不认为这个函数是正确的:
bool multiplication_is_safe(uint32_t a, uint32_t b) {
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits+b_bits<=32);
}
当乘法溢出时,它确实会返回false
,但当乘法没有溢出时,它也会返回false
。 例如,给定 a = 0x10000
且 b = 0x8000
,即使 a*b 的结果是 0x80000000
适合 32 位,此函数也返回 false
。 但是,如果您将 a 和 b 更改为 0x1ffff
和 0xffff
(它们具有相同的"最高一位位置"(,那么乘法实际上确实会溢出。 但是你不能只使用最高的位位置来判断。 您需要查看的不仅仅是顶部位来确定乘法是否会溢出。 事实上,你需要做部分或全部的实际乘法才能找出正确的答案。
类似地,您可以构造一个函数addition_is_safe
,该函数使用位位置检测"可能的溢出"(正向和负向(。 但是,除非您执行部分或全部实际添加,否则无法检测到"实际溢出"。
我相信在最坏的情况下,您将被迫进行完整的乘法或加法,所以我不确定您不会因为不让机器为您执行完整的乘法/加法来节省任何东西。
在数学上,如果将两个数字相加,则最多有 1 的进位 进入最长的地方。
这是绝对正确的(对于无符号的二进制数(,无一例外;你只是迷失在进一步的考虑中。因此,基于总和位数的addition_is_safe条件是:总和的最大位数必须小于可用位数。
bool addition_is_safe(uint32_t a, uint32_t b)
{
size_t a_bits=highestOneBitPosition(a), b_bits=highestOneBitPosition(b);
return (a_bits<b_bits?b_bits:a_bits)<32;
}
当然,您知道该函数的false
返回并不总是意味着会发生溢出,但true
返回意味着不会发生溢出。
您可以通过使用(a + b) < a || (a + b) < b
添加两个正整数来检查
溢出将使值为负(对于有符号整数(,或者将保留较小的正模式 32 余数(对于无符号(
正加到负永远不会溢出
两个负数应类似于两个正数