我目前正在嘗試找出一種對兩個 128.128 uint256 數字執行定點除法的具體方法。這似乎是一件相當簡單的事情,但無法撰寫解決方案。
對于兩個 64.64 定點數,以下作業正常。
function div64x64 (uint128 x, uint128 y) internal pure returns (uint128) {
unchecked {
require (y != 0);
uint256 answer = (uint256 (x) << 64) / y;
require (answer <= 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF);
return uint128 (answer);
}
}
但同樣的邏輯不適用于 uint256 128.128 定點數,因為您不能將 x 轉換為更大的 uint 型別來左移x。這是我為 128.128 解決這個問題的悲哀嘗試,它在輸出中不包含正確的小數,但我的嘗試確實包含了小數左邊的正確值。
function div128x128 (uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
require (y != 0);
uint256 xInt = x>>128;
uint256 xDecimal = x<<128;
uint256 yInt = y>>128;
uint256 yDecimal = y<<128;
uint256 hi = ((uint256(xInt) << 64)/yInt)<<64;
uint256 lo = ((uint256(xDecimal)<<64)/yDecimal);
require (hi lo <= MAX_128x128);
return hi lo;
}
}
有誰知道實作這一點的最佳方法,或者只是對如何做到這一點的概念性解釋,將不勝感激。提前致謝!
uj5u.com熱心網友回復:
好的,所以我將在這里為下一個人發布解決方案。這里的關鍵是一個更明顯的事實,即您可以將具有公分母的分數分解為兩個相加部分。例如12.525/9.5= (12/9.5) (.525/9.5),考慮到這一點,我們有一種方法可以將我們的數字分解為 2 個 uint256 數字,然后通過一些花哨的移位將它們連接起來。
function div128x128 (uint256 x, uint256 y) internal pure returns (uint256) {
unchecked {
//Require denominator != 0
require (y != 0);
// xDec = x & 2**128-1 i.e 128 precision 128 bits of padding on the left
uint256 xDec = x & 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF;
//xInt x *2**-128 i.e. 128 precision 128 bits of padding on the right
uint256 xInt = x >> 128;
//hi = xInt*2**256-1 /y ==> leave a full uint256 of bits to store the integer representation of the fractional decimal with 128.128 precision
uint256 hi = xInt*(MAX_128x128/y);
//xDec*2**256-1 /y ==> leave full uint256 of bits to store the integer representation of fractional decimal with 128.128 precision, right shift 128 bits since output should be the right 128 bits of precision on the output
uint256 lo = (xDec*(MAX_128x128/y))>>128;
/*Example: 12.525/9.5 := 12/9.5 .525/9.5<-- legal to break up a fraction into additive pieces with common deniminator in the example above just padding to fit 128.128 output in a uint256
*/
require (hi lo <= MAX_128x128);
return hi lo;
}
}
這是一種解決方案,只要滿足要求標準,它似乎就可以作業。幾乎毫無疑問,需要進行優化改進。但我在一些真實資料上對此進行了測驗,它似乎準確到 128.128 精度。
轉載請註明出處,本文鏈接:https://www.uj5u.com/caozuo/483289.html
上一篇:如何在顫振中自定義舍入?
下一篇:Linux namespace技術應用實踐--呼叫宿主機命令(tcpdump/ip/ps/top)檢查docker容器網路、行程狀態
