使用pion/opus解碼音頻檔案時,我偶爾會得到不正確的值。
我已將其除錯為以下代碼。當這個例程在 Opus 解碼器中運行時,我得到的值與在外部運行時不同?當兩個浮點數相加時,最右邊的位是不同的。隨著程式運行時間的延長,值的差異最終會成為一個問題。
這是錯誤還是預期行為?我不知道如何除錯程式的這種更深/轉儲狀態以了解更多資訊。
外部解碼器
package main
import (
"fmt"
"math"
)
func main() {
a := math.Float32frombits(uint32(955684399))
b := math.Float32frombits(uint32(927295728))
fmt.Printf("%b\n", math.Float32bits(a))
fmt.Printf("%b\n", math.Float32bits(b))
fmt.Printf("%b\n", math.Float32bits(a b))
}
退貨
111000111101101001011000101111
110111010001010110100011110000
111001000001111010000110100110
然后內部解碼器
fmt.Printf("%b\n", math.Float32bits(lpcVal))
fmt.Printf("%b\n", math.Float32bits(val))
fmt.Printf("%b\n", math.Float32bits(lpcVal val))
退貨
111000111101101001011000101111
110111010001010110100011110000
111001000001111010000110100111
uj5u.com熱心網友回復:
我猜這不是 Float32 而是 Float64 lpcval。val
如果是這種情況,那么您提出了兩種不同的操作:
- 在前一種情況下,你做
Float32bits(lpcval) Float32bits(val) - 在后一種情況下,你做
Float32bits(lpcval val)
兩個 32 位浮點數是二進制的:
1.11101101001011000101111 * 2^-14
1.10001010110100011110000 * 2^-17
確切的總和是
1.000011110100001101001101 * 2^-13
這是兩個可表示的 Float32 之間的精確關系
,結果四舍五入到具有偶數有效數的 Float32
1.00001111010000110100110 * 2^-13
但是lpcval并且val是 Float64:浮點數之后不是 23 位,而是 52 位(多 19 位)。
如果這 19 個以上的位中有一個位與零不同,則結果可能不是精確平局,但比精確平局略大。
一旦轉換為最近的 Float32,那將是
1.00001111010000110100111 * 2^-13
由于我們不知道這些低有效位中包含什么lpcval和包含什么,因此即使不使用 fma 操作,任何事情都可能發生。val
uj5u.com熱心網友回復:
這是因為Fused multiply and add. 多個浮點運算被合并為一個運算。
您可以在Go 語言規范#Floating_Point_Operators中閱讀更多相關資訊
我對代碼所做的更改是
- lpcVal = currentLPCVal * (aQ12 / 4096.0)
lpcVal = float32(lpcVal) float32(currentLPCVal)*float32(aQ12)/float32(4096.0)
感謝 Bryan C. Mills 在 Gophers slack 的#performance 頻道上回答這個問題。
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/514615.html
標籤:去浮点
上一篇:從os.stdout讀取
