<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          C語言居然還有Q格式這種用法?

          共 1200字,需瀏覽 3分鐘

           ·

          2020-12-26 12:12


          ID:小麥大叔

          作者:菜刀和小麥


          用過DSP的應(yīng)該都知道Q格式吧;


          1 前言

          Q格式是二進(jìn)制的定點(diǎn)數(shù)格式,相對(duì)于浮點(diǎn)數(shù),Q格式指定了相應(yīng)的小數(shù)位數(shù)和整數(shù)位數(shù),在沒有浮點(diǎn)運(yùn)算的平臺(tái)上,可以更快地對(duì)浮點(diǎn)數(shù)據(jù)進(jìn)行處理,以及應(yīng)用在需要恒定分辨率的程序中(浮點(diǎn)數(shù)的精度是會(huì)變化的);
          需要注意的是Q格式是概念上小數(shù)定點(diǎn),通過選擇常規(guī)的二進(jìn)制數(shù)整數(shù)位數(shù)和小數(shù)位數(shù),從而達(dá)到所需要的數(shù)值范圍和精度,這里可能有點(diǎn)抽象,下面繼續(xù)看介紹。

          2 Q數(shù)據(jù)的表示

          2.1 范圍和精度

          定點(diǎn)數(shù)通常表示為,其中m為整數(shù)個(gè)數(shù),n為小數(shù)個(gè)數(shù),其中最高位位符號(hào)位并且以二進(jìn)制補(bǔ)碼的形式存儲(chǔ);

          • 范圍:
          • 精度:

          無符號(hào)的用表示;

          • 范圍:
          • 精度:

          2.2 推導(dǎo)

          無符號(hào)Q格式數(shù)據(jù)的推導(dǎo)這里以一個(gè)16位無符號(hào)整數(shù)為例,所能表示的最大數(shù)據(jù)的二進(jìn)制形式如下圖所示;

          所以不難看出,的范圍大小和精度;根據(jù)等比數(shù)列求和公式得到,整數(shù)域最大值如下:

          小數(shù)域最大值如下:

          因此的范圍滿足 ;

          有符號(hào)Q格式數(shù)據(jù)的推導(dǎo)這里以一個(gè)16位有符號(hào)整數(shù)為例,所能表示的最大數(shù)據(jù)的二進(jìn)制形式如下圖所示;

          所以不難求出,的范圍大小和精度;根據(jù)等比數(shù)列求和公式得到,整數(shù)域最大值如下:

          小數(shù)域最大值如下:

          因此最大能表示的數(shù)為:;

          所能表示的最小數(shù)據(jù)的二進(jìn)制形式如下圖所示;

          可以從圖中看到,該數(shù)表示為;

          補(bǔ)充一下:負(fù)數(shù)在計(jì)算機(jī)中是補(bǔ)碼的形式存在的,補(bǔ)碼=反碼+1,符號(hào)位為1則表示為負(fù)數(shù);
          那么-4該如何表示呢?
          8 bit數(shù)據(jù)為例,如下所示;
          原碼:0B 0000 100
          反碼:0B 1111 011
          補(bǔ)碼:0B 1111 100

          綜上,可以得到有符號(hào)的范圍是:

          3 Q數(shù)據(jù)的運(yùn)算

          3.1 0x7FFF

          最大數(shù)的十六進(jìn)制為0x7FFF,如下圖所示;

          3.2 0x8000

          最小數(shù)的十六進(jìn)制為0X8000,如下圖所示;

          上述這兩種情況,下面都會(huì)用到。

          3.3 加法

          加法和減法需要兩個(gè)Q格式的數(shù)據(jù)定標(biāo)相同,即滿足以下條件;

          int16_t?q_add(int16_t?a,?int16_t?b)
          {
          ????return?a?+?b;
          }

          上面的程序其實(shí)并不安全,在一般的DSP芯片具有防止溢出的指令,但是通常需要做一下溢出檢測,具體如下所示;

          //https://great.blog.csdn.net/
          int16_t?q_add_sat(int16_t?a,?int16_t?b)
          {
          ????int16_t?result;
          ????int32_t?tmp;

          ????tmp?=?(int32_t)a?+?(int32_t)b;
          ????if?(tmp?>?0x7FFF)
          ????????tmp?=?0x7FFF;
          ????if?(tmp?-1?*?0x8000)
          ????????tmp?=?-1?*?0x8000;
          ????result?=?(int16_t)tmp;

          ????return?result;
          }

          3.4 減法

          類似于加法的操作,需要相同定標(biāo)的兩個(gè)Q格式數(shù)進(jìn)行相減,但是不會(huì)存在溢出的情況;

          //https://great.blog.csdn.net/
          int16_t?q_sub(int16_t?a,?int16_t?b)
          {
          ????return?a?-?b;
          }

          3.5 乘法

          乘法同樣需要考慮溢出的問題,這里通過sat16函數(shù),對(duì)溢出做了處理;

          //https://great.blog.csdn.net/
          //?precomputed?value:
          #define?K???(1?<
          ?
          //?saturate?to?range?of?int16_t
          int16_t?sat16(int32_t?x)
          {
          ????if?(x?>?0x7FFF)?return?0x7FFF;
          ????else?if?(x?-0x8000
          )?return?-0x8000;
          ????else?return?(int16_t)x;
          }

          int16_t?q_mul(int16_t?a,?int16_t?b)
          {
          ????int16_t?result;
          ????int32_t?temp;

          ????temp?=?(int32_t)a?*?(int32_t)b;?//?result?type?is?operand's?type
          ????//?Rounding;?mid?values?are?rounded?up
          ????temp?+=?K;
          ????//?Correct?by?dividing?by?base?and?saturate?result
          ????result?=?sat16(temp?>>?Q);

          ????return?result;
          }

          3.6 除法

          //https://great.blog.csdn.net/
          int16_t?q_div(int16_t?a,?int16_t?b)
          {
          ????/*?pre-multiply?by?the?base?(Upscale?to?Q16?so?that?the?result?will?be?in?Q8?format)?*/
          ????int32_t?temp?=?(int32_t)a?<????/*?Rounding:?mid?values?are?rounded?up?(down?for?negative?values).?*/
          ????/*?OR?compare?most?significant?bits?i.e.?if?(((temp?>>?31)?&?1)?==?((b?>>?15)?&?1))?*/
          ????if?((temp?>=?0?&&?b?>=?0)?||?(temp?0?&&?b?0))?{???
          ????????temp?+=?b?/?2;????/*?OR?shift?1?bit?i.e.?temp?+=?(b?>>?1);?*/
          ????}?else?{
          ????????temp?-=?b?/?2;????/*?OR?shift?1?bit?i.e.?temp?-=?(b?>>?1);?*/
          ????}
          ????return?(int16_t)(temp?/?b);
          }

          4 常見Q格式的數(shù)據(jù)范圍

          定點(diǎn)數(shù)和浮點(diǎn)數(shù)轉(zhuǎn)換的關(guān)系滿足以下公式:

          其中,m表示整數(shù)位數(shù),n表示小數(shù)位數(shù);

          #include?
          #include?
          #include?


          int?main()
          {
          ????//?0111?1111?1111?1111
          ????int16_t?q_max?=?32767;?//?0x7FFF
          ????//?1000?0000?0000?0000
          ????int16_t?q_min?=?-32768;?//?0x8000
          ????float?f_max?=?0;
          ????float?f_min?=?0;
          ????printf("\r\n");
          ????for?(int8_t?i?=?15;?i>=0;?i--)?{
          ????????f_max?=?(float)q_max?/?pow(2,i);
          ????????f_min?=?(float)q_min?/?pow(2,i);

          ????????printf("\t|?Q?%d?|?Q?%d.%d|?%f?|?%f?|\r\n",
          ???????????????i,(15-i),i,f_max,f_min);
          ????}

          ????return?0;
          }

          運(yùn)行得到結(jié)果如下所示;

          QQmnMaxMin
          Q 15Q 0.150.999969-1.000000
          Q 14Q 1.141.999939-2.000000
          Q 13Q 2.133.999878-4.000000
          Q 12Q 3.127.999756-8.000000
          Q 11Q 4.1115.999512-16.000000
          Q 10Q 5.1031.999023-32.000000
          Q 9Q 6.963.998047-64.000000
          Q 8Q 7.8127.996094-128.000000
          Q 7Q 8.7255.992188-256.000000
          Q 6Q 9.6511.984375-512.000000
          Q 5Q 10.51023.968750-1024.000000
          Q 4Q 11.42047.937500-2048.000000
          Q 3Q 12.34095.875000-4096.000000
          Q 2Q 13.28191.750000-8192.000000
          Q 1Q 14.116383.500000-16384.000000
          Q 0Q 15.032767.000000-32768.000000

          5 0x5f3759df

          Q格式雖然十分抽象,但是且看看這個(gè)數(shù)字0x5f3759df,感覺和Q格式有某種聯(lián)系,它是雷神之錘3中的一個(gè)算法的魔數(shù),畢竟游戲引擎需要充分考慮到效率,具體的由來可以看一下論文《Fast Inverse Square Root》,下面是源碼中剝出來的快速平方根算法;

          float?Q_rsqrt(?float?number?)
          {
          ?long?i;
          ?float?x2,?y;
          ?const?float?threehalfs?=?1.5F;

          ?x2?=?number?*?0.5F;
          ?y???=?number;
          ?i???=?*?(?long?*?)?&y;???//?evil?floating?point?bit?level?hacking
          ?i???=?0x5f3759df?-?(?i?>>?1?);?//?what?the?fuck?
          ?y???=?*?(?float?*?)?&i;
          ?y???=?y?*?(?threehalfs?-?(?x2?*?y?*?y?)?);?//?1st?iteration
          ?//?y???=?y?*?(?threehalfs?-?(?x2?*?y?*?y?)?);?//?2nd?iteration,?this?can?be?removed

          ?#ifndef?Q3_VM
          ?#ifdef?__linux__
          ???assert(?!isnan(y)?);?//?bk010122?-?FPE?
          ?#endif
          ?#endif
          ?return?y;
          }??

          6 總結(jié)

          本文介紹了Q格式的表示方式以及相應(yīng)的運(yùn)算,另外需要注意在Q格式運(yùn)算的時(shí)候,兩者定標(biāo)必須相同,對(duì)于數(shù)據(jù)的溢出檢測也要做相應(yīng)的處理。


          作者能力有限,文中難免有錯(cuò)誤和紕漏之處,請(qǐng)大佬們不吝賜教 創(chuàng)作不易,如果本文幫到了您;請(qǐng)幫忙點(diǎn)個(gè)贊 ???;


          長按下圖二維碼關(guān)注,獨(dú)自前進(jìn),走得快;結(jié)伴而行,走得遠(yuǎn);在這里除了肝出來的文章,還有一步一個(gè)腳印學(xué)習(xí)的點(diǎn)點(diǎn)滴滴;


          瀏覽 73
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  无码人妻免费视频 | 久久久久夜色精 | 亚洲最大网站在线观看 | 国产丝袜足交在线观看 | 欧美精品三级片 |