日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

解决求平均值出现加和导致的溢出问题

發布時間:2023/12/20 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 解决求平均值出现加和导致的溢出问题 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

解決求平均值出現加和導致的溢出問題

目錄

  • 解決求平均值出現加和導致的溢出問題
      • 方法一
      • 方法二
      • 方法三
      • 方法四
      • 方法五


試問求平均值能玩出什么樣的花樣來?

微軟大神@Raymond發表了一篇長文,講述的是關于求平均值的算法。

附上長文鏈接:https://devblogs.microsoft.com/oldnewthing/20220207-00/?p=106223#comments


求平均值這很簡單,小學時候的知識,無非就是N個數的加和在除以N,再簡單不過了。

對于無符號的兩個數求平均,我們通常這么寫:

(注:這里uint32_t以32位表示)

uint32_t average(uint32_t a, uint32_t b) {return (a + b) / 2; }

但是這樣就存在一個問題,當a和b兩個值都比較大的時候,a加b的結果會超出uint32_t的最大表示范圍,例如:

!!!!!!!!!average(0X80000000, 0X80000000) = 0!!!!!!!!!!!!!

所以為了避免這種情況,進行優化成這樣:

方法一

uint32_t average(uint32_t low, uint32_t high) {return low + (high - low) / 2; }

此方法需要知道大的那個值,當知道相加的兩個無符號整數中的較大值時,減去較小值再除二,就可以以提前減少長度,從而避免了數值溢出。

方法二

還有另一種算法不依賴于知道哪個值更大,已經被申請為美國專利于2016年到期:

uint32_t average(uint32_t a, uint32_t b) {return (a / 2) + (b / 2) + (a & b & 1); }

這個方法的訣竅在于將兩個數先進行除法縮小,然后同時對最低位進行位與,從而保證當兩個數都為奇數時,(a & b & 1)的結果能得到前面除法的一個補正。

方法三

該方法被稱為SWAR技術,它代表"寄存器中的SIMD"。

uint32_t average(uint32_t a, uint32_t b) {return (a & b) + (a ^ b) / 2; }

方法四

作者還提出了第二種思路,如果無符號32位整形的本身寄存器大小為64位的時候,或者編譯器支持的多字節運算,就可以使用強制轉換的方式:

uint32_t average(uint32_t a, uint32_t b) {// Suppose "unsigned" is a 32-bit type and// "unsigned long long" is a 64-bit type.return ((unsigned long long)a + b) / 2; }

不過要注意一點,使用這種方式要保證64位寄存器的前32位為0才可以,要不然計算出來的還是不對的。

方法五

該方法是該長文評論區的一位網友提出的:

uint32_t avg(uint32_t a, uint32_t b) {return (a & b) + ((a ^ b) / 2); }

這篇博客長文真就是微軟及各路大神的討論區,學無止境!


ends…

總結

以上是生活随笔為你收集整理的解决求平均值出现加和导致的溢出问题的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。