簡體   English   中英

double 到 uint64_t 的轉換

[英]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

  1. 18446744073709551616.0 / 1.0被評估為double 它的值為18446744073709551616.0 ,假設 IEEE754。 將其轉換為超出范圍的uint64_t的行為是未定義的。 未定義行為的一個常見表現形式是回繞到0。(這是大多數人認為會發生的情況,但是從超出范圍的浮點值轉換時行為是未定義的。)

  2. 使用表達式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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM