簡體   English   中英

在 uint32_t 范圍內變換 uint64_t 范圍

[英]Transform uint64_t range in uint32_t range

我想將 uint64_t 轉換為 uintw_t,其中 w in { 8, 16, 32} 保留“范圍”:

#include <cstdint>
#include <type_traits>

想法1:

f:[a,b]->[c,d] 與 f(a)=c, f(b)=d

讓 a = 0, b = 2^64-1, c = 0 和 d = 2^w-1。

如果 f(x) = mx+n 且 m = (dc)/(ba) = (2^w-1)/(2^64-1) < 1(我們需要 float 或 double...),n = 0

template<typename T, typename std::enable_if< std::is_unsigned_v <T>, T>::type = 0>
T transform_a(uint64_t n)
{
   constexpr double factor = static_cast<double>(~T(0)) / ~uint64_t(0);
   return static_cast<T>( factor*n );
}

template<>
uint64_t transform_a(uint64_t n)
{
   return n;
}

不要使用 uint16_t :c。

*想法2:

不能正常工作,我用 0xffffffffffffffffull 錯誤地測試了它...

template<typename T, typename std::enable_if< std::is_unsigned_v <T>, T>::type = 0>
T transform_b(uint64_t n)
{
     return static_cast<T>(n);
}

它將數字削減到較低的位。

想法3:

將字節分組並使用想法 1 重新映射。例如 uint32_t 中的 0xabcabcab 到 uint16_t:

abca -> [x] cabc -> [y] with ffff--> ff and 0000--> 00

想法4:

右移 (CHAR_BIT = 8...)

template<typename T, typename std::enable_if< std::is_unsigned_v <T>, T>::type = 0>
T transform_c(uint64_t n)
{
     return static_cast<T>(n>>(64 - 8*sizeof(T)));
}

template<>
uint64_t transform_c(uint64_t n)
{
   return n;
}

這個想法對我來說最有意義,但是它排除了沒有任何加權或舍入的次要位的影響。

https://quick-bench.com/q/Vs1W4UP35MCpJo5pY1ebXnM7QNo

在“實際使用”中,double 和 shift 版本對於 uint32_t 是等效的 在“沒有上下文的單獨使用”中,uint32_t 的 shift 版本更快

我的主要問題是,這種類型的轉換中最常見的是什么?

作為一個附加問題,是否有任何有效的方法可以通過某種舍入來執行此過程?

變速是標准的; 您可以通過在移位之前首先添加最低有效位的值的一半來獲得一些簡單的舍入,盡管這沒有實現正確的舍入到偶數,您必須擔心溢出。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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