2012-05-24 88 views
2

使用下面的代碼是否有任何錯誤(潛在的未定義行爲),是否將浮點值分配給long int?double到int的轉換

struct timespec t; 
t.tv_nsec = (some float value < 1) * 1E9 

回答

5

轉換將在編譯時完成。你可能會從編譯器得到一個警告,但是代碼沒有什麼錯誤,因爲用浮點常量初始化一個整數是非常傳統的。


我給初始化只是保持簡單。在代碼將是這樣的:

struct timespec t; t.tv_nsec = (some float value < 1) * 1E9; 

納秒到tv_nsec;有趣,但不應該有任何重大問題。練習中的雙精度有足夠的精度,以至於不會遇到太多麻煩,儘管偶爾可以從您的預期中獲得不同的值,因爲如果您不期望它會被截斷。這可能值得檢查;這取決於它對你的重要性。

我做了一個快速程序,看看是否有問題。承擔,這是運行時間計算,而不是編譯時間計算的頭腦,但結果可能是你類似:

#include <stdio.h> 

int main(void) 
{ 
    for (long l = 0; l < 1000000000; l++) 
    { 
     double d = l/1.0E9; 
     long r = d * 1E9; 
     if (r != l) 
      printf("%.9ld: %12.9f != %ld\n", l, d, r); 
    } 
    return 0; 
} 

它打印出其中分數值不整數值相匹配的值。一些體積大輸出的一小部分是:

031890838: 0.031890838 != 31890837 
031890839: 0.031890839 != 31890838 
031890840: 0.031890840 != 31890839 
031890851: 0.031890851 != 31890850 
031890852: 0.031890852 != 31890851 
031890853: 0.031890853 != 31890852 
031890864: 0.031890864 != 31890863 
031890865: 0.031890865 != 31890864 
031890866: 0.031890866 != 31890865 
031890877: 0.031890877 != 31890876 
031890878: 0.031890878 != 31890877 
031890879: 0.031890879 != 31890878 
031890890: 0.031890890 != 31890889 

雖然決不每一個有問題的值,我記錄(與wc -l)17075957出十億值(或所述值的約1.7%),用差異。這與Mac OS X 10.7.4上的GCC 4.1.2(Apple提供)相同。我用GCC 4.7.0得到了同樣的結果。大約需要30秒來生成數據。

一個由Kernighan和Plauger「編程風格的要素」我最喜歡的報價是:

  • 聰明的程序員曾經說過,「浮點數是像顆顆小樁。每當你移動一個,你就會失去一點沙子並拾起一點污垢。'

這表明問題很好。


注意,一個微不足道的變化使差錯率爲0:

long r = d * 1E9 + 0.5; 

也許你應該使用宏:

#define NANOSECONDS(x) ((x) * 1E9 + 0.5) 

long r = NANOSECONDS(d); 

你可以用較小的加常數; 0.1也將錯誤率降低爲0.

+0

謝謝。我給出的初始化只是爲了保持簡單。在代碼中它會像.. struct timespec t; t.tv_nsec =(一些浮點值<1)* 1E9。 – Manohar

+0

我已經取消了我原來的'你應該可以'的評論,並添加了一個擴展的答案'好吧,你將不得不決定是否適合你'告誡。 –

+0

謝謝。爲我的目的,這個警告是好的..讓我也更新我的問題,爲他人的利益。 – Manohar