我想使用两个浮子进行双重偏差(看来直接计算不支持双偏转)。

那可能吗?

这是我到目前为止尝试的(C#代码,应稍后进行HLSL):

int count = 7;
double value = 0.0073812398871474;
float f1 = (float)value;
float f2 = (float)((value - f1));
float r1 = f1 / count;
float r2 = f2 / count;
double result = (double)r1 + (double)r2;

0,00105446285765182(结果)

0,00105446284102106(正确的结果)

这与F1中的舍入有关。如果值是:

 double value = 0.0073812344471474;

然后结果是正确的。

有帮助吗?

解决方案

计算与浮点部分裂的计数相互量,然后使用Newton-Raphson互惠公式提高精度为完整的双重。

int count = 7;
double value = 0.0073812398871474;
double r = (double) (1.0f / count); // approximate reciprocal
r = r * (2.0 - count*r); // much better approximation
r = r * (2.0 - count*r); // should be full double precision by now.
double result = value * r;

其他提示

显然,您的算术错误对您而言尚不清楚。让我拼出它。

假设双重部分有两个部分,大部分和小部分,每个部分都有大约32位精确度。 (这并不是双打的工作方式,但它将用于我们的目的。)

浮子只有一部分。

想象一下,我们一次做32位,但要使所有内容保持双打:

double divisor = whatever;
double dividend = dividendbig + dividendlittle;
double bigquotient = dividendbig / divisor;

什么是大夸大?这是双重的。因此有两个部分。 BigQuotient等于BigQuotientbig + BigQuotientlittle。继续:

double littlequotient = dividendlittle / divisor;

同样,LittleQuotient是LittleQuotientbig + LittleQuotientlittle。现在我们添加商:

double quotient = bigquotient + littlequotient;

我们如何计算?商有两个部分。商人将设置为bigquotientbig。顾问将设置为bigquotientlittle + littlequotientbig。 LittleQuotientlittle被丢弃。

现在假设您在浮标中进行。你有:

float f1 = dividendbig;
float f2 = dividendlittle;
float r1 = f1 / divisor;

好,什么是R1?这是一个浮标。因此,它只有一部分。 R1是bigquotientbig。

float r2 = f2 / divisor;

什么是R2?这是一个浮标。因此,它只有一部分。 R2是Littlequotientbig。

double result = (double)r1 + (double)r2;

您将它们添加在一起,然后获得BigQuotientbig + LittleQuotientBig。 Bigquotientlittle怎么了? 您在那里失去了32位精确度,因此,您在此过程中获得32位的无限要求也就不足为奇了。 您根本没有想出正确的算法,以近似于32位的64位算术。

为了计算 (big + little)/divisor, ,你不能简单地做 (big / divisor) + (little / divisor). 。该代数规则在您时不适用 四舍五入每一个 分配!

现在很清楚吗?

那可能吗?

是的,只要你:

  • 接受不可避免的精确损失
  • 请记住,并非所有双打首先都适合浮标

更新

阅读您的评论(双重精度是必需的)之后,我的更新答案是:

不。

那么类似的事

result = value * (double)(1f / (float)count); ?

在那里,您只能分开两个浮子。我的演员比需要更多,但这是重要的。

编辑:
好的,所以您担心实际和圆形之间的区别,对吗?因此,只要一遍又一遍地做才能正确!

double result = 0;
double difference = value;
double total = 0;
float f1 = 0;
while (difference != 0)
{
    f1 = (float)difference;
    total += f1;
    difference = value - total;
    result += (double)(f1 / count);
}

...但是你知道,简单的答案仍然是“否”。这甚至没有捕获所有的舍入错误。从我的测试中,它最多可将不准确性降低至1E-17,大约有30%。

在评论中,您说:

当然,不应丧失精确度。这就是为什么我使用两个浮子。如果我接受丧失精度,那么我可以施放两个浮子并进行分区。

IEEE-754 single precision 值有24个重要的二进制数字。一种 double precision 值具有53个重要数字。您甚至不能将双重精度值表示为两个单个精确值而不会丢失准确性,更不用说算术了。

也就是说,是 可能的 仅使用双重和双精度扣除/加法和单个精度操作之间的转换进行正确的圆形双精度划分,但是如果您真的想正确执行此操作,那就很复杂了。您是否需要实际的IEEE-754正确的圆形,或者只是一个正确的答案,直到最后一两个位?

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top