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
是一个浮点值,它可能不可能完全容纳1.5530000000000000
。decimal
类型更适合保存这样的精确值。
如果你不能在套接字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。