添加两个双精度数给出错误结果

发布于 2024-07-30 06:48:36 字数 398 浏览 3 评论 0原文

我正在使用下面的一段代码,在一些神秘的情况下,添加的结果并不像预期的那样:

double _west = 9.482935905456543;
double _off = 0.00000093248155508263153;
double _lon = _west + _off;

// check for the expected result
Debug.Assert(_lon == 9.4829368379380981);
// sometimes i get 9.48293685913086 for _lon (which is wrong)

我在我的应用程序中使用了一些本机 DLL,并且我怀疑某些 DLL 造成了这种“错误计算” ,但我需要弄清楚是哪一个。 谁能告诉我如何找出问题的根源?

I'm using the following piece of code and under some mysterious circumstances the result of the addition is not as it's supposed to be:

double _west = 9.482935905456543;
double _off = 0.00000093248155508263153;
double _lon = _west + _off;

// check for the expected result
Debug.Assert(_lon == 9.4829368379380981);
// sometimes i get 9.48293685913086 for _lon (which is wrong)

I'm using some native DLLs within my application and i suspect that some DLL is responsible for this 'miscalculation', but i need to figure out which one.
Can anyone give me a hint how to figure out the root of my problem?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

挽清梦 2024-08-06 06:48:37

起初我认为这是一个舍入错误,但实际上你的断言是错误的。 尝试添加计算的整个结果,而不进行任意舍入。

尝试一下:

using System;

class Program
{
    static void Main()
    {
        double _west = 9.482935905456543;
        double _off = 0.00000093248155508263153;
        double _lon = _west + _off;

        // check for the expected result
        Console.WriteLine(_lon == 9.48293683793809808263153);       
    }
}

将来,如果您需要避免通常与 System.Single 和 相关的舍入错误,最好使用 System.Decimal >System.Double 类型。

然而,话虽这么说,但这里的情况并非如此。 通过在给定点任意舍入数字,您会假设该类型也会在同一点舍入,但这不是它的工作方式。 浮点数存储为其最大表示容量,只有达到该阈值后才会进行舍入。

At first I thought this was a rounding error but actually it is your assertion that is wrong. Try adding the entire result of your calculation without any arbitrary rounding on your part.

Try this:

using System;

class Program
{
    static void Main()
    {
        double _west = 9.482935905456543;
        double _off = 0.00000093248155508263153;
        double _lon = _west + _off;

        // check for the expected result
        Console.WriteLine(_lon == 9.48293683793809808263153);       
    }
}

In the future though it is best to use System.Decimal in cases where you need to avoid rounding errors that are usually associated with the System.Single and System.Double types.

That being said, however, this is not the case here. By arbitrarily rounding the number at a given point you are assuming that the type will also round at that same point which is not how it works. Floating point numbers are stored to their maximum representational capacity and only once that threshold has been reached does rounding take place.

静待花开 2024-08-06 06:48:37

问题是 Double 仅具有 15 - 16 位的精度(并且您在示例中似乎需要更高的精度),而 Decimal 的精度为 28 - 29。您如何在 Double 和 Decimal 之间进行转换?

The problem is that Double only has precision of 15 - 16 digits (and you seem to need more precision in your example) whereas Decimal has precision to 28 - 29. How are you converting between Double and Decimal?

半世晨晓 2024-08-06 06:48:37

您正受到舍入和精度问题的困扰。 请参阅。 小数可能有帮助。 请访问此处了解有关转换和舍入的详细信息。

来自 MSDN:

当您将 float 或 double 转换为十进制时,源值将转换为十进制表示形式,并根据需要四舍五入到小数点后第 28 位之后的最接近的数字。 根据源值的值,可能会出现以下结果之一:

如果源值太小而无法表示为小数,则结果为零。

如果源值为 NaN(不是数字)、无穷大或太大而无法表示为小数,则会引发 OverflowException。

You are being bitten by rounding and precision problems. See this. Decimal might help. Go here for details on conversions and rounding.

From MSDN:

When you convert float or double to decimal, the source value is converted to decimal representation and rounded to the nearest number after the 28th decimal place if required. Depending on the value of the source value, one of the following results may occur:

If the source value is too small to be represented as a decimal, the result becomes zero.

If the source value is NaN (not a number), infinity, or too large to be represented as a decimal, an OverflowException is thrown.

空名 2024-08-06 06:48:37

您无法用二进制系统中的浮点数准确地表示十进制系统中的每个浮点数,这甚至与十进制数的“小”程度没有直接关系,有些数字只是不“适合”基数 - 2 很好。

在大多数情况下,使用较长的位宽度会有所帮助,但并非总是如此。

要以 Decimal(128 位浮点)精度指定常量,请使用以下声明:

decimal _west = 9.482935905456543m;
decimal _off = 0.00000093248155508263153m;
decimal _lon = _west + _off;

You cannot represent every floating point number in the decimal system with a floating point in a binary system accurately, this isn't even directly related to how "small" the decimal number is, some numbers just don't "fit" in base-2 nicely.

Using a longer bit width can help in most cases, but not always.

To specify your constants in Decimal (128-bit floating point ) precision, use this declaration:

decimal _west = 9.482935905456543m;
decimal _off = 0.00000093248155508263153m;
decimal _lon = _west + _off;
迷雾森÷林ヴ 2024-08-06 06:48:36

double 并不完全准确,请尝试使用decimal 代替

使用double 和float 相对于decimal 的优点是性能

double is not completely accurate, try using decimal instead

The advanteage of using double and float over decimal is performance

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文