簡體   English   中英

如何將unsigned long long轉換為double

[英]How to convert unsigned long long to double

我有一個隨機數生成器如下。

uint64_t s[ 2 ];

uint64_t next(void) { 
    uint64_t s1 = s[ 0 ];
    const uint64_t s0 = s[ 1 ];
    s[ 0 ] = s0;
    s1 ^= s1 << 23; // a
    return ( s[ 1 ] = ( s1 ^ s0 ^ ( s1 >> 17 ) ^ ( s0 >> 26 ) ) ) + s0; // b, c
}

事實上我想在范圍(0,1)中獲得雙打。 一種選擇是在我的代碼中執行此操作

#define M_RAN_INVM64 5.42101086242752217003726400434970855e-20
[..]
double u1;
u1 = next()*M_RAN_INVM64;
  1. 我擔心我會失去精確度,而且這也取決於平台。
  2. 我不希望得到值0或1。

一種選擇是將next()轉換為帶符號的long long,乘以M_RAN_INVM64然后再加0.5。 然后我可以添加2 ^(64)/ 2以確保我從未得到0。

編輯:為了在范圍(0,1)中轉換任何正unsigned long longlong double ,您可以使用以下步驟因子:

 long double step = ((long double) 1.0) / ULLONG_MAX

其他信息使用浮點數時,也許您可​​以考慮系統的限制。 以下內容可以幫助您了解系統中的浮點數:

有一種可移植的方法來獲取編譯程序的系統中最小的浮點數。

這可以通過使用標准庫<float.h>來實現。
有了它,您可以使用以下宏常量:

 FLT_MIN    // Smallest positive float number in your system  
 DBL_MIN    // Smallest positive double number in your system  
 LDBL_MIN   // Smallest positive long double number in your system  

此外,您可以考慮類似“epsilon”的常量,它為您提供有關給定類型的最小正數的信息,例如1.0!= 1.0 +“epsilon”。
當您嘗試獲得盡可能接近1.0的數字時,這可以幫助您,但仍然不同:

FLT_EPSILON  
DBL_EPSILON  
LDBL_EPSILON  

參見,例如: float.h(ANSI)

接受答復后:

double數以對數方式分布。 有0.25到0.5的double 0.25到0.5 - 假設基數2 double

假設double是IEEE binary64:...

為了在[0.0到1.0]范圍內獲得double均勻 (線性)分布,可以僅使用2 ^ 53個值。 所以從next()的結果中拋出11位

uint64_t u1 = next();
u1 >>= 11;
// or
u1 &= 0x001FFFFFFFFFFFFF;
if (u1 == 0) ThrowOutZero();

// convert to (0.0 to 1.0)
double d = u1 / 9007199254740992.0;  // Divide by 2^53

暫無
暫無

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

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