[英]Double to uint64_t conversion
以下演示程序演示了一些我不理解的行為。
#include <string>
#include <limits>
#include <iostream>
constexpr double bits64 = 18446744073709551616.0; // 2^64
void diff_hash(double diff)
{
double hash = bits64 / diff;
uint64_t hash_64_1 = hash;
uint64_t hash_64_2 = hash < std::numeric_limits<uint64_t>::max() ? hash : std::numeric_limits<uint64_t>::max();
uint64_t hash_64_3 = std::numeric_limits<uint64_t>::max();
if(hash < hash_64_3){
hash_64_3 = hash;
}
std::cout << "hash_64_1: " << hash_64_1 << ", " << "hash_64_2: " << hash_64_2 << ", " << "hash_64_3: " << hash_64_3 << std::endl;
}
int main()
{
diff_hash(1);
return 0;
}
output
hash_64_1: 0, hash_64_2: 0, hash_64_3: 18446744073709551615
問題:
1.) 為什么hash_64_1 == 0
? 分配的事件值顯然是最大 64 值
2.) 為什么hash_64_2 == 0
? 我確認如果我將行更改為
uint64_t hash_64_2 = hash < std::numeric_limits<uint64_t>::max() ? hash : std::numeric_limits<uint32_t>::max();
hash_64_2
的值最大 32 值
鏈接到 Wandbox 示例https://wandbox.org/permlink/HyXRX2CiNgIIpYkQ
18446744073709551616.0 / 1.0
被評估為double
。 它的值為18446744073709551616.0
,假設 IEEE754。 將其轉換為超出范圍的uint64_t
的行為是未定義的。 未定義行為的一個常見表現形式是回繞到0。(這是大多數人認為會發生的情況,但是從超出范圍的浮點值轉換時行為是未定義的。)
使用表達式hash < std::numeric_limits<uint64_t>::max()
,右側隱式轉換為double
。 但該數字不能表示為double
精度數,因此四舍五入為最接近的double
精度數,即18446744073709551616.0
。 因此hash_64_2
也是 0。
1.) 為什么 hash_64_1 == 0? 分配的事件值顯然是最大 64 值
這實際上很難說清楚。 hash
明顯大於最大 64 值。 將不可表示的(目標類型)浮點數轉換為 integer 的行為未定義。
“被分配的顯然是最大 64 個值”--> 減一。
最大uint64_t
值為18446744073709551615
,而不是18446744073709551616
。
看到的效果是由於將超出范圍的double
轉換為uint64_t
的 UB。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.