double vs string中的舍入错误.格式化相同的数字

本文关键字:格式化 数字 错误 舍入 vs string double | 更新日期: 2023-09-27 18:15:38

我有一个具有实际值的双精度(从调试器中看到)val = 1.5530000000000002

然而,如果我像string.Format("{0}", val)一样打印它,我得到"1.553",这是我正在寻找的现实值。

1.5530000000000002来自一些套接字API,我不能改变。但我需要1.553.

我该怎么办?

请注意,我每秒收到数千个这些。我无法承担Math类进行修补或来回转换。安慰吗?

double vs string中的舍入错误.格式化相同的数字

问题是double是一个浮点值,它可能不可能完全容纳1.5530000000000000decimal类型更适合保存这样的精确值。

如果你不能在套接字API中将double更改为decimal,那么你别无选择,只能使用数学来解决这个问题。在这种情况下,您需要将double转换为decimal,然后执行数学运算以调整所需的精度。

你可以这样做:

double value = 1.5530000000000002;
decimal rounded = decimal.Round((decimal)value, 3);

Math类每秒可以执行数千个这样的操作。所以你所需要做的是Math.Floor(val, 3)Math.Round(val, 3)

基本上,您需要使用十进制数据类型,而不是双精度类型。小数可以存储精确值,其精度范围;

一定要用Double吗?如果没有,您可以使用Decimal.Round(val, 3),例如。

我决定将它们升级为整型。我可以这样做,因为我知道数字中有多少位有效数字。

int real = (int)(dbl * multiplier);

我确信小数会更慢,因为我没有x128的CPU和内存总线。使用数学永远不是问题。

很抱歉,之前使用了float。

编辑 OK。所以我得到了So现在不再是免费的。每个问题现在都需要注意,这需要花费时间。下面是回答为什么我不会使用小数和数学的代码。

class Program
{
    static void Main(string[] args)
    {
        Start();
        Console.ReadLine();                
    }
    static int TESTS = 10;
    static int LOOPS = 50000;
    static double d1 = 1.5530000000000002;
    static double d2 = 1.5531;
    static double dResult;
    static int iResult;
    static decimal cResult;
    static void Start()
    {
        // actual test
        for (int x = 0; x < TESTS; x++)
        {
            Stopwatch sw = new Stopwatch();
            long tick1, tick2, tick3;
            sw.Start();
            for (int j = 0; j < LOOPS; j++)
            {
                dResult = Math.Round(d1 / 2.0, 4);
                dResult = Math.Round(d2 / 2.0, 4);
            }
            sw.Stop();
            tick1 = sw.ElapsedTicks;
            sw.Restart();
            for (int j = 0; j < LOOPS; j++)
            {
                iResult = (int)(d1 / 2.0 * 10000.0);
                iResult = (int)(d2 / 2.0 * 10000.0);
            }
            sw.Stop();
            tick2 = sw.ElapsedTicks;
            sw.Restart();
            for (int j = 0; j < LOOPS; j++)
            {
                cResult = decimal.Round((decimal)d1, 4);
                cResult = decimal.Round((decimal)d2, 4);
            }
            sw.Stop();
            tick3 = sw.ElapsedTicks;
            Console.WriteLine("Math {0} Int {1} Decimal {2}", tick1, tick2, tick3);
        }
    }
}

第一部分是Math,第二部分是我打算使用的(转换为int),第三部分是Decimals。

在我的i7上的结果如下-分别为12K, 700, 35K。