该代码中 std::max 用法的解释?
Explanation of the usage of std::max in that code?
我不确定我是否应该在 codereview.stackexchange.com 上发布这个问题。不管怎样,我们开始吧...
请考虑以下代码片段,它是从 here 中摘录的文字(我只是更改了格式),并且已在德国计算机杂志 c' 中打印(以精简形式), 23/2019 期:
while (lo <= hi) {
std::streamoff pos = std::streamoff((uint64_t(lo) + uint64_t(hi)) / 2);
pos -= pos % std::streamoff(PasswordHashAndCount::size);
pos = std::max<int64_t>(0, pos);
phc.read(mInputFile, pos);
++nReads;
if (hash > phc.hash) {
lo = pos + std::streamoff(PasswordHashAndCount::size);
}
else if (hash < phc.hash) {
hi = pos - std::streamoff(PasswordHashAndCount::size);
}
else {
safe_assign(readCount, nReads);
return phc;
}
}
为什么我们需要第四行pos = std::max<int64_t>(0, pos);
?
从第二行,我们看到 pos
等于或大于 0
,因为它是两个本身属于 uint64_t
类型的数之和的一半.
第三行不能使pos
低于0
。证明:
为简单起见,将 pos
替换为 A
,将 std::streamoff(PasswordHashAndCount::size)
替换为 B
。然后第三行是A -= A % B
,相当于A = A - (A % B)
,其中A
和B
是整数,A
等于或大于0
,并且 B
大于 0
(因为 ::size
总是大于 0)。
首先,如果A < B
,A % B = A
。这样的话,第三行就变成了A = A - A
,即A = 0
.
其次,如果A == B
,A % B
变为A % A
,即0
。所以,第三行就变成了A = A - 0
,相当于空操作。换句话说, A
在那种情况下不会改变;值得注意的是,它仍然是 0
或更大。
第三,如果A > B
,A - (A % B)
大于0
。这是因为 A % B
小于 B
,因此 A - (A % B)
大于 A - B
。后者又大于0
,因为这里的条件是A > B
.
当然,A > B
、A < B
、A == B
这三种情况都是可能发生的情况。在每种情况下,第三行都会为 A
分配一个新值,即 0
或正数。
回到原来的变量命名,这意味着pos
在第三行执行后总是0
或大于
鉴于此,我不明白第四行的作用。毕竟,如果 pos
是 0
或正数,max(0, pos)
总是等同于 pos
。
我错过了什么?以上推理有没有错误?
让我们考虑一下它到底做了什么:
std::streamoff pos = std::streamoff((uint64_t(lo) + uint64_t(hi)) / 2);
pos = std::max<int64_t>(0, pos);
std::streamoff
是一些实现定义的有符号整数类型。让我们考虑一个 64 位或更小的类型的情况: pos
的值不会因转换为 int64_t
而改变,因为类型更宽,在赋值中转换回来时也不会改变,因为原始值必须是可表示的。
让我们考虑一种情况,其中 std::streamoff
是 128 位或更宽的类型:值来自 (uint64_t(lo) + uint64_t(hi)) / 2
,不能超过最大值 int64_t
。因此,在这种情况下,该值也无法通过转换更改。
因此,使用int64_t
在任何情况下都没有效果。
The third line can't make pow lower than 0
Is there an error in the reasoning above?
我找不到任何错误。
Given that, I don't understand what the fourth line does.
该行对程序的行为完全没有影响。如果该行写成:
,程序将具有相同的行为
;
此外,在您在台式机或服务器上找到的大多数系统上,std::streamoff
和 int64_t
具有相同的位数。
我不确定我是否应该在 codereview.stackexchange.com 上发布这个问题。不管怎样,我们开始吧...
请考虑以下代码片段,它是从 here 中摘录的文字(我只是更改了格式),并且已在德国计算机杂志 c' 中打印(以精简形式), 23/2019 期:
while (lo <= hi) {
std::streamoff pos = std::streamoff((uint64_t(lo) + uint64_t(hi)) / 2);
pos -= pos % std::streamoff(PasswordHashAndCount::size);
pos = std::max<int64_t>(0, pos);
phc.read(mInputFile, pos);
++nReads;
if (hash > phc.hash) {
lo = pos + std::streamoff(PasswordHashAndCount::size);
}
else if (hash < phc.hash) {
hi = pos - std::streamoff(PasswordHashAndCount::size);
}
else {
safe_assign(readCount, nReads);
return phc;
}
}
为什么我们需要第四行pos = std::max<int64_t>(0, pos);
?
从第二行,我们看到 pos
等于或大于 0
,因为它是两个本身属于 uint64_t
类型的数之和的一半.
第三行不能使pos
低于0
。证明:
为简单起见,将 pos
替换为 A
,将 std::streamoff(PasswordHashAndCount::size)
替换为 B
。然后第三行是A -= A % B
,相当于A = A - (A % B)
,其中A
和B
是整数,A
等于或大于0
,并且 B
大于 0
(因为 ::size
总是大于 0)。
首先,如果A < B
,A % B = A
。这样的话,第三行就变成了A = A - A
,即A = 0
.
其次,如果A == B
,A % B
变为A % A
,即0
。所以,第三行就变成了A = A - 0
,相当于空操作。换句话说, A
在那种情况下不会改变;值得注意的是,它仍然是 0
或更大。
第三,如果A > B
,A - (A % B)
大于0
。这是因为 A % B
小于 B
,因此 A - (A % B)
大于 A - B
。后者又大于0
,因为这里的条件是A > B
.
当然,A > B
、A < B
、A == B
这三种情况都是可能发生的情况。在每种情况下,第三行都会为 A
分配一个新值,即 0
或正数。
回到原来的变量命名,这意味着pos
在第三行执行后总是0
或大于
鉴于此,我不明白第四行的作用。毕竟,如果 pos
是 0
或正数,max(0, pos)
总是等同于 pos
。
我错过了什么?以上推理有没有错误?
让我们考虑一下它到底做了什么:
std::streamoff pos = std::streamoff((uint64_t(lo) + uint64_t(hi)) / 2); pos = std::max<int64_t>(0, pos);
std::streamoff
是一些实现定义的有符号整数类型。让我们考虑一个 64 位或更小的类型的情况: pos
的值不会因转换为 int64_t
而改变,因为类型更宽,在赋值中转换回来时也不会改变,因为原始值必须是可表示的。
让我们考虑一种情况,其中 std::streamoff
是 128 位或更宽的类型:值来自 (uint64_t(lo) + uint64_t(hi)) / 2
,不能超过最大值 int64_t
。因此,在这种情况下,该值也无法通过转换更改。
因此,使用int64_t
在任何情况下都没有效果。
The third line can't make pow lower than 0
Is there an error in the reasoning above?
我找不到任何错误。
Given that, I don't understand what the fourth line does.
该行对程序的行为完全没有影响。如果该行写成:
,程序将具有相同的行为;
此外,在您在台式机或服务器上找到的大多数系统上,std::streamoff
和 int64_t
具有相同的位数。