我想将边界为#include <stdio.h>
#include <string.h>
int main (void)
{
char word[20];
do
{
scanf("%c", word);
}
while (strlen (word) > 0 && strlen (word) <20);
printf("the word is %s", word);
}
的范围分成相等或接近相等的间隔double
。
我在GNU Scientific Library中找到了合适的功能:
N>=2
但是,什么时候
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]
如何在不求助于长算术的情况下实现均匀性(我已经有了长算术解决方案,但它丑陋且缓慢)?位扭曲和x86(x86-64,因此没有扩展精度)汇编程序是可以接受的。
更新:
需要通用的解决方案,而不以[0x410D6FA800000000,
0x410D6FA800000001,
0x410D6FA800000002,
0x410D6FA800000003]
,xmin
具有相等的指数和符号为前提:
xmax
和xmin
可以是除无穷大和NaN之外的任何值(为简单起见,也可能不包括非规格化值)。xmax
xmin < xmax
答案 0 :(得分:0)
我看到两个选择:将操作重新排序为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";
}
}
答案 1 :(得分:0)
x87仍然存在于x86-64中,并且主流OS的64位内核可以正确保存/恢复64位进程的x87状态。尽管您可能已经读过,但x87仍可以在64位代码中完全使用。
在Windows之外(即在其他任何地方使用的x86-64 System V ABI),long double
是80位本机x87本机格式。如果您不关心可移植到ARM / PowerPC或任何其他在硬件中仅具有64位精度的东西,这可能只会解决x86 / x86-64的精度问题。
最好仅将long double
用于函数内部的临时对象。
我不确定要使编译器发出80位扩展FP数学,您必须在Windows上做什么。在asm中当然是有可能的,并且受内核支持,但是工具链和ABI使其使用起来很不方便。
x87仅比标量SSE数学要慢一些。不过,80位加载/存储的速度特别慢,就像在Skylake上4而不是1(https://agner.org/optimize/一样,并且fld m80
还要有几个周期的额外延迟。
对于必须通过存储和使用x87 fild
将int转换为FP的循环而言,它的速度最多可能比对于64位double的SSE2好的编译器要慢2倍。
当然long double
将阻止自动矢量化。