2013-02-19 445 views
0

我從一個嵌入式設備中讀取四個16位寄存器,它們代表一個64位整數。讀取函數在uint16_t中讀取它們,我想將它轉換爲浮點數32.如果我這樣做,我會得到警告left shift count> =寬度類型[默認啓用]。將int64轉換爲float32 in c

uint16_t u1,u2,u3,u4; 
u1=readregister(); 
u2=readregister(); 
u3=readregister(); 
u4=readregister(); 

float num11 = (float) (u1 << 48);  
float num22 = (float) (u2 << 32); 
float num33 = (float) (u3 << 16); 
float num44 = (float) u4; 
float numm= num11+num22+num33+num44; 
printf("%f\n", numm); 

準確度呢?

回答

2

這樣來做:

float num11 = (uint64_t) u1 << 48; 
/* ... */ 

如果編譯器警告(其中C不要求),因爲uint64_t轉換float的,你可以添加一個額外float投:

float num11 = (float) ((uint64_t) u1 << 48); 

這將擺脫警告。

出於效率和精度的原因,最好先將您的4 uint16_t轉換爲單個uint64_t,然後執行從uint64_tfloat的單次轉換。

+1

我不確定效率,但構建一個精確的'uint64_t'然後轉換爲float絕對是最精確的,例如'u4 == 1'和'u2 << 32 + u3 << 16'正好在兩個可表示的「浮動」之間的中間。 – 2013-02-19 20:59:35

+1

關於效率,這個問題提到了一個嵌入式設備。沒有FPU,所有的浮點操作都是用軟件完成的,需要很多CPU週期。一個運行時間整數轉換爲「float」轉換肯定比四個要好。 – ouah 2013-02-19 21:07:06

+0

對。我正在考慮具有FPU但沒有本機64位整數類型的嵌入式設備。 :) – 2013-02-19 21:11:53

1

一種方式來做到這一點是:

#include <math.h> 

float numm = (float) u4 + ldexpf(u3, 16) + ldexpf(u2, 32) + ldexpf(u1, 48); 

這並不需要你的嵌入式編譯器提供任何其他整數大小比你已經有了uint16_t,只需要ldexpf()

這計算float,其在移位整數u1,...,u4的數學和的一個ULP內。

+1

這會導致多次舍入,並不總是產生正確舍入的結果。 – 2013-02-19 20:56:48

+0

@EricPostpischil這是對的,因此我的陳述是計算出的「float」在數學和的一個ULP範圍內。 – 2013-02-19 21:00:35

+0

@EricPostpischil有一種方法可以做到這一點,它涉及到「粘點」的想法,但現在在我的時區已經太晚了。 – 2013-02-19 21:02:19