为什么除法结果为零而不是小数?

教我自己C,发现当我做一个温度转换的方程时,除非把分数改成小数,否则它将不起作用。 即

tempC=(.555*(tempF-32))将工作,但tempC=((5/9)*(tempF-32))将不起作用。

为什么?
根据C底漆加它应该工作,因为我为tempC和tempF使用浮动。

看起来你在第二种情况下有整数除法:

 tempC=((5/9)*(tempF-32)) 

5 / 9将被截断为零。

为了解决这个问题,你需要使其中一个浮点types:

 tempC=((5./9.)*(tempF-32)) 

其他人已经告诉你,5和9都是整数,这就是为什么结果被截断的原因。

我将添加一个解释,以更深入地了解行之间真正发生的事情:

 double tempC; double tempF; tempC = (5/9) * (tempF-32); // removed unnecessary parenthesis 

根据您的特定编译器使用的从左到右或从右到左的评估顺序 ,它将开始评估子expression式(5/9)(tempF-32)

你无法知道这两个评估中的哪一个! 因为评估顺序在C中是未指定的行为,这意味着编译器可以做任何事情,而不需要logging如何。 因此,不应该依赖评估的顺序编写代码,否则将不可移植,可能不正确。


让我们假设一个特定的编译器使用从左到右的评估。

  • C的运算符优先级规则决定开始评估的位置。 括号运算符在C中具有最高优先级,因此编译器将首先评估遇到的第一个括号内容。
  • 因此,它将从expression式(5/9)
  • 编译器检查每个操作数的types。
  • 在这种情况下,它们都是常量整数文字。 整数文字在C中总是inttypes
  • 由于两个操作数都是相同的types,所以不需要隐式types转换。
  • 计算是在一个inttypes上执行的,结果是一个int

所以现在expression式被评估为:

tempC = (int)0 * (tempF-32);

  • 编译器然后评估(tempF-32)。
  • 操作数的types是doubleint 。 它们不是同一types的。
  • 隐式types转换发生。 在这种情况下称为平衡(正式称为通常的算术转换 )。
  • 平衡规则说,如果一种types是双重的,另一种是别的,另一种types应该被转换成双倍。
  • 在隐式types转换之后,expression式现在相当于(double)tempF - (double)32.0 。 计算结果并将其存储在doubletypes的临时不可见variables中。 这个不可见variables存储在CPU寄存器或堆栈中。

现在的expression可以被描述为

tempC = (int)result1 * (double)result2;

其中“result1”为0,“result2”为tempF – 32.0的结果。

  • 编译器然后评估这个新的expression式。 它find一个int和一个double
  • 再次,平衡发生,int被转换为double。
  • 乘法是在两个双打上执行的,结果是双倍的。
  • 结果存储在另一个临时的不可见variables中。

tempC = (double)result3;

  • 编译器评估这个新的expression式。 它发现一个双倍应该保存在一个双。 这不是问题,所以不需要隐式转换。 “result3”存储在tempC中。

当你做5/9,5和9都是整数和整数除法发生。 整数除法的结果是一个整数,它是两个操作数的商。 因此,5/9的情况下的商是0,并且由于您乘以0,所以tempC会出现为0.为了不具有整数除法,两个操作数中的至less一个必须是float

例如,如果您使用5.0 / 9或5 / 9.0或5.0 / 9.0,它将按预期工作。

5/9是一个整数除法,不是浮点除法。 这就是为什么你得到错误的结果。

使5或9浮点variables,你会得到正确的答案。

像5.0 / 9或5 / 9.0

5/9是一个整数expression式,因此它被截断为0.您的编译器应该警告您这个,否则您应该查看启用警告。

如果将5/9放在括号中,则将首先计算这个值,因为这些是两个整数,所以将通过整数除法完成,结果将为0,然后评估其余的expression式。

您可以重新排列expression式,以便首先发生浮动转换:

tempC=((5/9)*(tempF-32));tempC=(5*(tempF-32))/9;

或者当然,正如别人所说的,使用浮点常量。