提问人:tamir1020 提问时间:1/11/2022 更新时间:1/14/2022 访问量:984
将 double 转换为 float 出错 - C#
Convert double to float goes wrong - C#
问:
我需要计算类型的边界rectangleF
由于某种原因,从到的铸造没有得到应有的精确评估double
float
这是此类计算的一个例子
float MinX = 0f, MaxX = 0f;
float MinY = 0f, MaxY = 0f;
float BoundsWidth = 0.2f;
float BoundsHeight = 0.1f;
double BoundsY = 2333638.6551984739;
double BoundsX = 895.0999755859375;
MinX = (float)BoundsX;
MinY = (float)BoundsY;
var MaxX_Defect = BoundsX + BoundsWidth;
var MaxY_Defect = BoundsY + BoundsHeight;
MaxX = (float)(MaxX_Defect);
MaxY = (float)(MaxY_Defect);
当我尝试计算最高值时,它的评估结果不是MaxY-MinY
0
0.1f
我该如何解决这个问题?
答:
该行将 .1 转换为 中最接近的值,结果为 0.100000001490116119384765625float BoundsHeight = 0.1f;
float
BoundsHeight
该行同样转换为 ,设置为 2,333,638.6551984739489853382110595703125。double BoundsY = 2,333,638.6551984739;
double
BoundsY
该行将其转换为 ,设置为 2,333,638.75。float MinY = BoundsY;
float
MinY
该行使用(我假设;我不熟悉 C# 语义),设置为 2,333,638.7551984754391014575958251953125。double MaxY_Defect = BoundsY + BoundsHeight;
double
MaxY_Defect
该行将其转换为 ,设置为 2,333,638.75。float MaxY = (float)(MaxY_Defect);
float
MaxY
然后我们可以看到它并具有相同的值,所以当然是零。MinY
MaxY
MaxY-MinY
很简单,没有足够的精度来区分 2,333,638.6551984739489853382110595703125 和 2,333,638.7551984754391014575958251953125。在比例为 2,333,638 时,格式中相邻可表示数字之间的距离为 .25。这是因为该格式有 24 位的有效值(浮点表示的分数部分)。2,333,638 介于 221 和 222 之间,因此其浮点表示中的指数将有效数缩放为具有表示从 2 21 到 2−2 的值的位(从 21 到 −2,包括24 个位置)。因此,将有效数在其最低位上改变 1 会将表示的数字改变 2−2 = .25。float
float
因此,当 2,333,638.655...和 2,333,638.755...转换为 ,它们具有相同的结果 2,333,638.75。float
您不能用于区分在该量级下如此接近的坐标或大小。您可以使用或许可将坐标平移为更接近原点(因此它们的大小更小,将它们放在分辨率更精细的区域)。float
double
float
只要最终结果很小,就可以使用 进行中间计算,但仍然使用 很好地表示最终结果。double
float
有关浮点运算的更多信息,我推荐 Muller、Brunie、de Dinechin、Jeannerod、Joldes、Lefèvre、Melquiond、Revol 和 Torres 的《浮点算术手册》。此处似乎提供了先前版本的 PDF。官方的 IEEE 754-2019 浮点运算标准可在此处获得。
评论
float
精度不够。你可以试试这个: ,它将输出 0。float a = 2333638; float b = a + 0.1f; Console.WriteLine(b - a);
double
float
double
double
double
b-a
double
2333638000000000