我在C#中實現了一個64位定點簽名的31.32數值類型,基於long
。到目前爲止,加法和減法都非常好。然而,乘法有一個惱人的情況,我試圖解決。64位定點乘法錯誤
我的當前算法由每個操作數分裂成其最高和最低顯著32位,進行4次乘法成4個多頭,添加這些多頭的相關比特。這裏是代碼:
public static Fix64 operator *(Fix64 x, Fix64 y) {
var xl = x.m_rawValue; // underlying long of x
var yl = y.m_rawValue; // underlying long of y
var xlow = xl & 0x00000000FFFFFFFF; // take the 32 lowest bits of x
var xhigh = xl >> 32; // take the 32 highest bits of x
var ylow = yl & 0x00000000FFFFFFFF; // take the 32 lowest bits of y
var yhigh = yl >> 32; // take the 32 highest bits of y
// perform multiplications
var lowlow = xlow * ylow;
var lowhigh = xlow * yhigh;
var highlow = xhigh * ylow;
var highhigh = xhigh * yhigh;
// take the highest bits of lowlow and the lowest of highhigh
var loResult = lowlow >> 32;
var midResult1 = lowhigh;
var midResult2 = highlow;
var hiResult = highhigh << 32;
// add everything together and build result
var finalResult = loResult + midResult1 + midResult2 + hiResult;
return new Fix64(finalResult); // this constructor just copies the parameter into m_rawValue
}
這在一般情況下工作,但在許多情況下失敗。也就是說,結果是1.0(十進制值),對於操作數的極小值或大值通常是這樣。下面是我的單元測試的一些結果(FromRaw()被直接從長值建立一個Fix64不轉移它的方法):
Failed for FromRaw(-1) * FromRaw(-1): expected 0 but got -1
Failed for FromRaw(-4) * FromRaw(6791302811978701836): expected -1.4726290525868535041809082031 but got -2,4726290525868535041809082031
Failed for FromRaw(2265950765) * FromRaw(17179869183): expected 2.1103311001788824796676635742 but got 1,1103311001788824796676635742
我想在紙上計算出的這個邏輯但我有點卡住了。我怎樣才能解決這個問題?
你在做什麼進位?另外,我不完全理解翻譯......「2265950765」的等效數值是多少? – mellamokb
是的,進位位呢? –
我不熟悉C#的整數升級規則 - 值是lowlow等32位還是32x32乘法會自動給出64位結果? – hobbs