我何时应该使用整数进行算术运算而不是float / double

时间:2016-06-14 19:10:04

标签: c# arithmetic-expressions

有些SO用户告诉我,我不应该使用float / double作为学生成绩的东西,请参阅最后的评论:SequenceEqual() is not equal with custom class and float values

“因为在整数中进行所有算术,然后在最后一刻转换为合适的显示格式比尝试以浮点格式进行算术更容易和更安全。”

我尝试了他所说的但结果并不令人满意。

   int grade1 = 580;
   int grade2 = 210;
   var average = (grade1 + grade2) / 2;       
   string result = string.Format("{0:0.0}", average / 100);

结果是“3,0”

    double grade3 = 5.80d;
    double grade4 = 2.10d;
    double average1 = (grade3 + grade4) / 2;
    double averageFinal = Math.Round(average1);
    string result1 = string.Format("{0:0.0}", averageFinal);

result1 “4,0”

我希望4,0因为3,95会导致4,0。这是有效的,因为我使用Math.Round,它只能用于双精度或小数。这不适用于整数。

那我在这里错了什么?

5 个答案:

答案 0 :(得分:5)

首先,你引用的具体问题是让我非常烦恼的问题。你几乎从不想在整数运算中出现问题而然后将它转换为浮点类型,因为计算将完全用整数完成。我希望C#编译器警告这个;我一直都这么看。

其次,优选整数或十进制算术加倍算术的原因是双精度只能以完美的精度表示分母为2的幂的分数。当你说双倍的0.1时,你得不到1/10,因为1/10不是分母,其分母是2的任何幂。你得到最接近的分数为1/10, 在分母中具有2的幂。

这通常是“足够接近”,直到它不是。当你有接近硬截止点的小错误时,这是​​特别令人讨厌的。例如,你想说一个学生必须有一个2.4 GPA才能满足某些条件,并且你在分母中涉及两个分数的计算恰好碰巧到了2.39999999999999999956 ......

现在,您不必通过十进制算法摆脱这些问题;十进制算术具有相同的限制:它只能表示分母中权数为10的分数。您尝试表示1/3,并且您将在每次计算时得到一个小但非零的错误。

因此,标准建议是:如果您正在进行任何计算,您在进行计算时需要精确算术,这些计算涉及分子中10的幂,例如财务计算,请使用小数,或者完全执行计算 整数,适当缩放。如果您正在进行涉及物理数量的计算,那么计算中没有固有的“基础”,那么请使用“double”。

那么为什么要使用整数而不是十进制,反之亦然?整数运算可以更小更快;小数需要更多的时间和空间。但最终您不应该担心这些小的性能差异:选择最准确反映您正在使用的数学域的数据类型,并使用它。

答案 1 :(得分:3)

您需要"在最后一刻转换为合适的显示格式"

string result = string.Format("{0:0.0}", average / 100.0);

答案 2 :(得分:0)

我认为你选择了两个给出的错误选项。知道Eric,如果你已经清楚自己正在进行舍入,平均等浮点运算,那么他就不会建议使用整数。不使用double的原因是因为它们不能始终精确地表示十进制值(您无法在1.1中完全代表double)。

如果您想使用浮点数学,但仍保持最高28位有效数字的小数精度,请使用decimal

decimal grade1 = 580;
decimal grade2 = 210;
var average = (grade1 + grade2) / 2;     
average = Math.Round(average);  
string result = string.Format("{0:0.0}", average);

答案 3 :(得分:0)

average是int,100是int。 当你做平均值/ 100时,你有一个整数除以整数,你将在其中返回一个整数,但由于3.95不是整数,它被截断为3。

如果你想得到一个float或double作为结果,则必须在算术中包含double或float。

在这种情况下,您可以将结果转换为双倍(双倍)平均值/ 100或除以双倍,平均值/ 100.0

你想要远离用浮点数/小数进行太多算术运算直到最后一秒的唯一原因就是你不能在开始时插入长物理方程中的变量值的原因,你失去精确度。当您必须处理数字的浮点表示时,这是数值方法中非常重要的概念,例如机器epsilon。

答案 4 :(得分:0)

不那么容易。

如果成绩是整数格式,则以整数存储即可。

但我会将十进制PRIOR转换为执行任何数学运算以从数学中删除舍入误差,除非您特别想要整数数学。

对于财务计算,建议使用小数。实际上后缀是m。但

decimal (C# Reference)

  

decimal关键字表示128位数据类型。相比   浮点类型,十进制类型具有更高的精度和a   较小的范围,这使其适合金融和货币   计算。十进制类型的近似范围和精度   如下表所示。

FloatDouble是浮点类型。你得到一个更大的范围,然后小数,但精度更低。十进制有足够大的等级范围。

decimal grade3 = 5.80m;
decimal grade4 = 2.10m;
decimal average1 = (grade3 + grade4) / 2;

int grade1 = 580;
int grade2 = 210;
var average = (grade1 + grade2) / 2;
string result = string.Format("{0:0.0}", average / 100);  // 3.0
Debug.WriteLine(result);

decimal avg = ((decimal)grade1 + (decimal)grade2) / 200m;  // 3.95
Debug.WriteLine(avg);
Debug.WriteLine(string.Format("{0:0.0}", avg));  // 4.0