【问题标题】:What is difference between F = (9/5 * C) + 32 and F = (C *9/5) + 32 ? Precedence? [duplicate]F = (9/5 * C) + 32 和 F = (C *9/5) + 32 有什么区别?优先级? [复制]
【发布时间】:2019-08-20 15:26:08
【问题描述】:

F = (C * 9/5 ) + 32 和 F = (9/5 * C) + 32 产生两个不同的结果,尽管 C 的输入是相同的。我意识到运算符有某种优先级,但我不确定。乘法先于除法吗?

输入 20 在第一种情况下给出华氏值 68(正确的值),在第二种情况下给出 52。

#include<stdio.h>

int main()
{
    float cel , fahr ; 
    printf("Enter the temperature(C): ");
    scanf("%f",&cel);
    fahr = (9/5 * celt is  ) + 32;
    printf("\nThe temperature in fahranheit is %f ",fahr);

}

预期的结果是 68,但上面代码的结果是 52。如果我切换“9/5”和“cel”的位置,它会给出正确的结果。这是为什么呢?

【问题讨论】:

标签: c operators operator-precedence


【解决方案1】:

乘法和除法在 C 中具有相同的优先级,并且具有从左到右的结合性。所以,

  • F = (C * 9/5 ) + 32 等价于 F = ((C * 9)/5) + 32
  • F = (9/5 * C) + 32 等价于 F = ((9/5) * C) + 32

这两个表达式在代数上是等价的,除了 C 定义了int / int = int,丢弃了余数。所以,9/5 不是您预期的 1.8,而是 1。

要通过两个ints 相除得到浮点结果,您需要将至少一个操作数转换为floatdouble。所以不要写9/5,写:

  • 9.0/5.09.0/59/5.01.8,即为您提供 double,或
  • 9.0f/5.0f9.0f/59/5.0f1.8f,这会给你一个 float

【讨论】:

  • 所以F = ((C * 9)/5) + 32 会比F = ((9/5) * C) + 32 更精确
  • 不,表达式:9/5 由于分数的整数截断,结果为 1
  • 恕我直言,最好是使用所有浮点数,因为问题是关于温度:F = 9.0/5.0 * C + 32.0; 在转换温度时,最好以科学家的身份思考,而不是作为汇编程序员 :) OMG!这个程序是K&R书的第二个例子!!!没人看吗?
【解决方案2】:

是的,优先级(和整数运算)。

他们的评价是这样的:

F = ((C * 9)/5 ) + 32;

对比

F = ((9/5) * C) + 32;

C 进行整数运算的方式(它将整数截断为零)使得第二个不正确(9/5 是一)。

改为使用9.f5.f32.f。这样,优先级不会有太大变化(并且您会得到正确的结果)。

【讨论】:

    【解决方案3】:

    这个表达式

    C * 9/5
    

    从左到右计算,因为使用的运算符具有相同的优先级。

    所以,它被评估为

    ( C * 9 ) / 5
    

    每次计算子表达式时,编译器都会确定所用操作数的通用类型。

    子表达式的常用类型

    C * 9
    

    根据通常的算术转换是浮点数。所以这个子表达式的结果有float类型和整个表达式的结果

    ( C * 9 ) / 5
    

    对应的是float类型。

    这个表达式

    9/5 * C
    

    被评估为

    (9/5) * C
    

    作为子表达式的两个操作数

    9/5
    

    是整数,则使用整数运算,子表达式的结果也是整数。

    为了避免操作数顺序的依赖,你可以例如写

    (9.f/5) * C
    

    (9/5.0f) * C
    

    在这种情况下,子表达式

    8.0f/5
    

    8/5.0f
    

    被评估为带有浮点数的表达式。

    【讨论】:

    • 为什么每个人都坚持使用整数,而所有的算术都必须在浮点数中完成?使用这种方法,C 的新手会认为使用浮点文字是一项昂贵的任务。与现实相去甚远。
    【解决方案4】:

    除了优先级问题,9/5 的结果是1。如果它被写出来,它会更像预期的那样工作

    9.0/5       or
    9/5.0        or
    9.0/5.0       or (even)
    1.8
    

    【讨论】:

    • 不要忘记f 后缀。 OP 正在处理floats。
    • @JL2210:除了最挑剔的编译器外,不需要显式类型后缀f。该表达式将被评估为double,并在分配给fahr 时截断为float
    • 是的,但一般来说,尽量避免隐式类型更改(当你不注意时,它们会让你大吃一惊)。
    • @JL2210 隐式类型转换是一种语言的特性。避免它们是愚蠢的;这样做首先否定了使用高阶语言的效用。自然,您必须学会避免一些陷阱(这个问题展示了一个花哨的陷阱),但我不得不不同意您关于“避免隐式类型更改”的全面建议。总的来说,它们都很好。
    • 隐式类型转换可能(并且经常会)产生程序员所期望的值。这就是编译器(启用警告时)输出有关问题的警告消息的原因
    猜你喜欢
    • 2012-04-14
    • 2013-01-16
    • 2020-04-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-10
    相关资源
    最近更新 更多