[英]Split range into uniform intervals
我想將具有double
邊框的范圍分割為N>=2
等於或接近相等的間隔。
我在GNU Scientific Library中找到了一個合適的函數:
make_uniform (double range[], size_t n, double xmin, double xmax)
{
size_t i;
for (i = 0; i <= n; i++)
{
double f1 = ((double) (n-i) / (double) n);
double f2 = ((double) i / (double) n);
range[i] = f1 * xmin + f2 * xmax;
}
}
但是,什么時候
xmin = 241141
(二進制0x410D6FA800000000
)
xmax = 241141.0000000001
(二進制0x410D6FA800000003
)
N = 3
功能產生
[0x410D6FA800000000,
0x410D6FA800000000,
0x410D6FA800000002,
0x410D6FA800000003]
而不是期望
[0x410D6FA800000000,
0x410D6FA800000001,
0x410D6FA800000002,
0x410D6FA800000003]
如何在不使用長算術的情況下實現均勻性(我已經有一個很長的算術解決方案,但它很丑陋而且很慢)? bit twiddling和x86(x86-64,因此沒有擴展精度)匯編程序例程是可以接受的。
更新:
需要一般的解決方案,沒有前提是xmin
, xmax
具有相等的指數和符號:
xmin
和xmax
可以是除無窮大和NaN之外的任何值(為簡單起見,可能還排除非規范化值)。 xmin < xmax
(1<<11)-1>=N>=2
我看到兩個選擇:將操作重新排序為xmin + (i * (xmax - xmin)) / n
,或直接處理二進制表示。 這是兩個例子。
#include <iostream>
#include <iomanip>
int main() {
double xmin = 241141;
double xmax = 241141.0000000001;
size_t n = 3, i;
double range[4];
std::cout << std::setprecision(std::numeric_limits<double>::digits10) << std::fixed;
for (i = 0; i <= n; i++) {
range[i] = xmin + (i * (xmax - xmin)) / n;
std::cout << range[i] << "\n";
}
std::cout << "\n";
auto uxmin = reinterpret_cast<unsigned long long&>(xmin);
auto uxmax = reinterpret_cast<unsigned long long&>(xmax);
for (i = 0; i <= n; i++) {
auto rangei = ((n-i) * uxmin + i * uxmax) / n;
range[i] = reinterpret_cast<double&>(rangei);
std::cout << range[i] << "\n";
}
}
x87仍然存在於x86-64中,主流操作系統的64位內核可以正確保存/恢復64位進程的x87狀態。 盡管您可能已閱讀過,但x87完全可用於64位代碼。
在Windows之外(即x86-64 System V ABI在其他地方使用), long double
是80位原生x87原生格式。 如果您不關心ARM / PowerPC的可移植性/在HW中只有64位精度的其他任何東西,這可能只解決x86 / x86-64的精度問題。
可能最好只使用long double
的功能內的臨時工具。
我不確定你要在Windows上做什么來讓編譯器發出80位擴展FP數學。 它在asm中肯定是可能的,並且由內核支持,但是工具鏈和ABI使得使用起來不方便。
x87僅比當前CPU上的標量SSE數學慢一些。 但是,80位加載/存儲速度非常慢,例如Skylake上的4 uops而不是1( https://agner.org/optimize/ ),以及fld m80
的幾個周期額外延遲。
對於你的循環必須通過存儲和使用x87 fild
將int轉換為FP,它可能最多比一個好的編譯器可以用SSE2為64位double的速度慢2倍。
當然, long double
會阻止自動矢量化。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.