【问题标题】:Issue with fahrenheit conversion formula in C [duplicate]C中的华氏转换公式问题[重复]
【发布时间】:2013-04-18 00:31:57
【问题描述】:

当用 C 编写程序将摄氏度转换为华氏度时,以下公式给出了错误的输出:

    int fahr = 9 / 5 * celsius + 32;

现在,我知道这可能是 9/5 被解释为整数的问题,但我不明白的是,使用 double 或 float它仍然会给出相同的错误输出。

奇怪的是,尽管将类型设置为int,但以下公式给出了正确的输出:

int fahr = celsius / 5 * 9 + 32;

此外,我注意到即使像下面这样简单的事情,当类型设置为 double 时,输出仍然是 1.0 而不是 1.8:

 double x = 9 / 5;
 printf("%lf\n", x);

我读过这个帖子:

C program to convert Fahrenheit to Celsius

但我仍然不明白为什么 int fahr = celsius / 5 * 9 + 32; 有效但 int fahr = 9/5 * celsius+32; 无效?

【问题讨论】:

  • 因为 9 和 5 被视为整数。试试 9.0/5.0
  • 这是一个典型的新手错误。
  • 因为真正的男人使用 Kelvin ;)

标签: c


【解决方案1】:

你正在用整数做数学运算。这个表达式:

9 / 5

在 C 中生成 1。当你说你使用了 double 或 float 时,你可能只是更改了 fahr 的类型,这对发生在右侧的操作没有任何作用assignemtn 运算符。要获得正确的行为,您还需要将这些常量中的至少一个设为 double:

9.0 / 5

同样,在此声明中:

double x = 9 / 5;

您仍在进行整数数学运算,然后将结果分配给double 变量。没有其他事情发生。通过执行以下操作之一,您将得到正确答案:

double x = 9.0 / 5;
double x = 9 / 5.0;
double x = 9.0 / 5.0;

这个表达式的原因:

int fahr = celsius / 5 * 9 + 32;

似乎工作只是一个操作顺序 - 在这里你将输入除以 5 然后乘以 9,而不是先进行常量操作。您仍然可以通过以下方式获得更准确的答案:

int fahr = celsius * 9 / 5 + 32;

除此之外,您还可以在此表达式中进行浮点数学运算:

int fahr = celsius * 9.0 / 5 + 32;

如果你想用整数做原始计算,你当然可以——你只需要在除之前乘:

int fahr = 9 * celsius / 5 + 32;

这个表达式等同于上面使用的表达式之一。

【讨论】:

  • 我明白这一点。请阅读整篇文章。
  • @Tangler,我不认为你这样做。我进行了编辑以更好地解释。
  • 好的,那为什么会这样:int fahr = celsius / 5 * 9 + 32 ?
  • 我添加了另一个编辑来涵盖这一点。这是因为操作是从左到右进行的。
  • 好的,谢谢。关于您的陈述“在这里您将输入除以 5,然后乘以 9,而不是先进行常量运算。”,我仍然有点不清楚,因为我也将 celsius 设置为 int,因此它真的只是除以整数,就像 9/5。所以你是说使用 int 变量而不是常量是有区别的(即使变量被分配了与常量相同的值)?
【解决方案2】:

我仍然不明白为什么 int fahr = celsius / 5 * 9 + 32; 有效,但 int fahr = 9/5 * celsius+32; 无效

对于前者,您可能将celsius 声明为float 或double,从而使整个右侧都这样评估。假设你使用了float,结果如下:

celsius / 5 * 9 + 32
(celsius / 5.0) * 9 + 32
(celsius / 5.0 * 9.0) + 32
(celsius / 5.0 * 9.0 + 32.0)

对于后者,9/5 是整数运算,在其余数学运算以浮点形式发生之前计算为 1。在这种情况下:

9 / 5 * celsius + 32
1 * celsius + 32 // Because of this, you get an incorrect answer
celsius + 32
celsius + 32.0

注意左边的类型无关紧要;右侧的评估不考虑这一点。

更新:你说celsius是int,这意味着你碰巧碰巧用5的倍数进行测试,给你一个正确的整数在对语句的其余部分进行有效的整数运算之前,将结果传递给celsius / 5。在您的第二个示例中,成为 5 的倍数对您没有帮助。

无论如何,现在您知道自己为什么幸运了,但是链接的问题为您提供了当celsius 不是5 的倍数时有效的公式的答案:使用浮点数学,如那里的所有答案所示。

【讨论】:

  • 不,摄氏度也被声明为 int。上面有人提到这是一个操作顺序的事情,但我不明白为什么,因为它仍然在某个时候潜水两个整数。
  • 那么你很幸运,它是5 的倍数,让celsius / 5 给你一个数学上正确的答案。
  • @Tangler:Darshan 是对的。尝试使用不是 5 的倍数的值;你会看到一个截断错误。
  • @KeithThompson 好的,谢谢,你是对的(我没有收到错误,但我确实得到了不正确的输出)。例如,使用摄氏度 25、27 或 28 都给出 77 华氏度。真的不知道为什么讲师当时将它用作解决方案(他确实有一个循环,只能以 10 为增量步进摄氏度,然后将转换输出为表格 - 不过似乎仍然是一种不好的做事方式)
  • 感谢您的更新确实解决了让我感到困惑的主要问题(即为什么其他公式仍然有效),这就是为什么我将您的答案标记为已接受的答案。
【解决方案3】:

(在大多数情况下)评估每个表达式或子表达式的类型,而不考虑其出现的上下文。

在此声明中:

double x = 9 / 5;

初始化表达式为9 / 5;它由两个int 表达式和一个除法运算符组成。因为/ 的操作数是int 类型,所以它是int 除法,产生int 值。由于整数除法被截断,结果是1,类型为int。

然后使用该表达式的结果来初始化x。由于x 的类型为double,因此该值会从int 隐式转换为double,从而导致x 持有值1.0。

如果你想让x的值是1.8,你需要做浮点除法,也就是说你需要浮点操作数。最简单、最清晰的方法是:

double x = 9.0 / 5.0;

还有其他几种(恕我直言不太清楚)方法。如果/ 运算符有两个操作数,一个是int 类型,一个是double 类型,则int 操作数将提升为double,因此其中任何一个也将x 设置为1.8 :

double x = 9.0 / 5;
/* or */
double x = 9 / 5.0;

但要小心这种方法:

double y = 9 / 5 / 3.0;

这相当于:

double y = (9 / 5) / 3.0;

它将9 / 5 计算为int,产生1,然后将该结果提升为double 并将其除以3.0,产生0.333333333。

关键是表达式的上下文不会对表达式或其操作数强加类型;表达式被评估为好像它是孤立的,然后结果可能会根据其上下文进行转换。

【讨论】:

  • 9/5 是 1,而不是 0。
  • @CarlNorum:当然,如果你要学究的话。 8-)} 说真的,感谢您接受!
  • 没问题,你关于(9/5)/3.0 的最后一个例子也会产生0.33333。
  • @CarlNorum:显然不是我的日子。
  • 我很确定我们都去过那里。 ;-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多