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]));
最後看看各種型別的範圍:
速查表:c浮點數之移位操作vs聯合體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
浮點數操作
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是四位元組的...