浮點數移位操作和型別轉換問題

2021-09-07 10:16:21 字數 3946 閱讀 6253

y0 = (regioninfolist[i].minx*mat[3] - regioninfolist[i].miny*mat[0] - (mat[2] * mat[3] - mat[0] * mat[5])) / (mat[1] * mat[3] - mat[0] * mat[4]);

x0 = (regioninfolist[i].minx*mat[4] - regioninfolist[i].miny*mat[1] - (mat[2] * mat[4] - mat[1] * mat[5])) / (mat[0] * mat[4] - mat[1] * mat[3]);

y1 = (regioninfolist[i].maxx*mat[3] - regioninfolist[i].maxy*mat[0] - (mat[2] * mat[3] - mat[0] * mat[5])) / (mat[1] * mat[3] - mat[0] * mat[4]);

x1 = (regioninfolist[i].maxx*mat[4] - regioninfolist[i].maxy*mat[1] - (mat[2] * mat[4] - mat[1] * mat[5])) / (mat[0] * mat[4] - mat[1] * mat[3]);

需要mat改為左移16位的int型別;先想直接將mat的每個元素(mat[i]>>16)就行了,但是這樣做跟直接用double型別的沒有區別。而且這樣做有錯誤!最多到1.0

int a = 66519;

double b = a >> 16;

printf("移位結果:%lf\n", b); //輸出1.000000

然後查c語言浮點數不能進行移位操作

c語言中,有符號資料的移位操作和無符號的移位操作不同,無符號的移位操作為邏輯移位,即高位捨棄,低位補0;高位補0,低位捨棄。有符號的整數型別的移位操作為算數移位,也就是最高位保持不變,負數高位移位後還是保持「1」,正數移位後還是保持「0」,而其他位和邏輯移位一樣。

c語言不支援浮點數的移位操作,浮點數的儲存和整型數的儲存不同,並不是直接將數值表示成二進位制形式儲存,儲存的方式在下表呈現,具體的在這裡不多說,浮點數直接移位後基本沒有什麼意義,但是有時候還是需要進行移位操作,比如使用串列埠/iic/can等通訊時,需要將資料一位元組一位元組的傳送,對於浮點數來說,就需要將浮點數分解成位元組,這樣常用的有兩種方法,一是利用聯合體的特點將浮點數分解,二是利用移位操作,移位操作需要一些技巧。

浮點數不能直接使用移位操作,整型可以,所以將浮點數轉化為整型數進行移位是可行的,但是這裡的型別轉化不是類似(int)a這樣的強制型別轉換,而是將儲存整型的資料記憶體的解釋規則轉化為整型,比如進行如下操作:

float a;

uint32_t *data = (uint32_t *)&a;

經過這樣的操作後,儲存資料a的記憶體,就可以使用data或者(uint32_t )&a解釋成整型,並且對data或者(uint32_t )&a進行移位操作把浮點數分解為單個位元組並且不改變每一位的值。

下面的兩段**都可以將浮點數分解為單位元組並進行操作,比較來看,在將資料(並不限制為浮點數)分解為位元組倍數的型別時,聯合體的操作更加簡單易懂,但是移位操作沒有這一限制,比使用聯合體靈活,但也相對複雜,比較來看,各有千秋。

//浮點數的移位操作

#include "stdint.h"

#include "stdio.h"

int main(void)

for (int i = 0;i < 8;i++)

printf("%f", result);

system("pause");

}//使用聯合體達到移位操作效果

#include "stdio.h"

#include "stdint.h"

#include "string.h"

int main(void)

test, test2;

double x = 5.1;

double re;

int i;

test.val = x;

for (i = 0; i < 8; i++)

re = test2.val;

printf("%f", re);

}

** 浮點數移位轉化為位元組操作**

本身等式就是上下除的形式,然後可以抵消;遇到的坑就是(mat[2] * (long long)mat[3])這些地方都要用強制型別轉換。然後強制型別轉換需要在運算前進行,計算後轉換是沒有效果的

//注意溢位處理

y0 = (((long long)(regioninfolist[i].minx*mat[3] - regioninfolist[i].miny*mat[0]) << 16) - ((mat[2] * (long long)mat[3]) - (mat[0] * (long long)mat[5]))) / ((mat[1] * (long long)mat[3]) - (mat[0] * (long long)mat[4]));

x0 = (((long long)(regioninfolist[i].minx*mat[4] - regioninfolist[i].miny*mat[1]) << 16) - ((mat[2] * (long long)mat[4]) - (mat[1] * (long long)mat[5]))) / ((mat[0] * (long long)mat[4]) - (mat[1] * (long long)mat[3]));

y1 = (((long long)(regioninfolist[i].maxx*mat[3] - regioninfolist[i].maxy*mat[0]) << 16) - ((mat[2] * (long long)mat[3]) - (mat[0] * (long long)mat[5]))) / ((mat[1] * (long long)mat[3]) - (mat[0] * (long long)mat[4]));

x1 = (((long long)(regioninfolist[i].maxx*mat[4] - regioninfolist[i].maxy*mat[1]) << 16) - ((mat[2] * (long long)mat[4]) - (mat[1] * (long long)mat[5]))) / ((mat[0] * (long long)mat[4]) - (mat[1] * (long long)mat[3]));

最後看看各種型別的範圍:

速查表:

char -128 ~ +127 (1 byte)

short -32767 ~ + 32768 (2 bytes)

unsigned short 0 ~ 65535 (2 bytes)

int -2147483648 ~ +2147483647 (4 bytes)

unsigned int 0 ~ 4294967295 (4 bytes)

long == int

long long -9223372036854775808 ~ +9223372036854775807 (8 bytes)

double 1.7 * 10^308 (8 bytes)

unsigned int 0~4294967295

long long的最大值:9223372036854775807

long long的最小值:-9223372036854775808

unsigned long long的最大值:18446744073709551615

__int64的最大值:9223372036854775807

__int64的最小值:-9223372036854775808

unsigned __int64的最大值:18446744073709551615

c浮點數之移位操作vs聯合體

浮點數操作

float fx 49.03f int nx fx 100 printf d nx 執行上述 結果 4902。用vc6.0,2005,gcc編譯執行結果都是一樣。為什麼會這樣呢,是因為浮點數運算具有不精確性。其實編譯上面的 編譯器會有警告的。warning c4244 initializing co...

PHP 浮點數操作

f 3.14159 使用sprintf對浮點數小數點後三位四捨五入 f new sprintf 3f f echo 3.14159小數點後三位四捨五入 f new.f round round f,3 echo 3.14159小數點後三位四捨五入 round函式 f round.進一法取浮點數的整數 ...

浮點數精度問題

一 例子 首先我們去編譯器試試 double a 1.9 通過新增監視檢視a的值 會發現a的值是1.8999999 二 開始今天的學習 在最開始學c 的時候並沒有對浮點數進行很深入的學習,認為浮點不就是小數嘛,首先在c 的巨集裡面有 flt max 和 flt min 的定義,float是四位元組的...