在C和Objective-C中,我们应该使用0.5f还是0.5?

我看到作者使用的地方有很多:

sprite.anchorPoint = CGPointMake(1, 0.5f); 

也就是说,为什么不使用0.5代替0.5f – 是否有使用0.5f优势?

0.5double常数,而0.5ffloat常数。

使用0.5f有优势吗?

是。 您要么为计算指定类型(读取:精度),要么避免隐式缩小(以及关联的编译器警告)。

您提供的示例并不引人注目,除了避免编译器警告或只是对参数类型非常严格。

然而,对于双倍精度而言,不太明显的促销可能是昂贵的。

要回答“我们应该使用0.5f还是0.5” :因为每个都有适当的时间,所以你应该在程序中使用两者 。 您应该使用适合您所需的计算/精度的类型,您传递的参数的类型,或者适用于表达式中其他值的类型。 这就像整数一样 – 有适当的时间考虑宽度,并有适当的时间后缀(例如UL )。 有时候区别很重要,而且(很自然地)它不重要。

常量0.5在Objective-C中声明一个double,将f放在最后 – 0.5f将常量声明为(32位)float。
在Objective-C / Cpost中看一下数字/浮点数后的“f” 。

尾随f强制常量为单精度float ,因为浮点常量默认为double s。 这对于之前的一些编译器修订来说更为重要,因为我不认为有双重自动类型转换为浮点数,因为编译器无法确保没有这样做的副作用。 结果是,当只需要单精度浮点寄存器时,许多代码保持f指定符以避免加载双精度浮点寄存器时的循环。

当双常量适当时使用浮点常量会产生后果,反之亦然:

  1. 许多常数会改变价值。 例如,.3不等于.3f。 当源文本包含十进制数字时,编译器必须将其转换为浮点数表示的值。 1999 C标准要求将其转换为最接近的较高可表示值或最接近的较低可表示值。 一个好的编译器会将它转换为任一方向上最接近的值,如果是平局,将选择最低位为零的那个。 (返回这样的值称为“正确舍入”。)当正确舍入到通常使用的浮点格式时,.3变为0x1.3333333333333p-2,。3f变为0x1.333334p-2。 (这些是hex浮点常数。“0x”之后和“p”之前的部分是hex数字,“p”之后的部分是2的十进制指数。因此0x3.cp4是0x3.c乘以2 4 ,即(3 + 12/16)⋅24= 60.)

  2. 表达式更改类型。 当算术运算符的操作数包含float和double操作数时,float操作数将转换为double。 这可能导致计算值发生变化。 1999 C标准允许编译器表示具有比其类型要求更高的精度和范围的浮点值,因此浮点值可以保存在双寄存器中并使用双算术运算。 但是,如果使用双常量,则需要编译器使用双精度算法。 因此,如果浮点x包含0x1.24924ap-3(大约1/7),则“x + .5f”可能产生0x1.492492p-1而“x + .5”必须产生0x1.4924928p-1。

  3. 在Objective C,C ++和其他可以根据参数类型选择调用哪个函数的语言中,更改参数的类型可以完全改变执行的代码。 调用“foo(.5f)”可以调用分配内存的例程,而“foo(.5)”写入网络套接字。 这通常是被调用对象的糟糕设计,但是在特殊情况下,对象需要对其参数的类型敏感。 此外,这在技术上可能在C中(如在tgmath.h中),但它很少(并且通常涉及使用预处理器将“foo”定义为测试其参数大小的表达式)。

以上列表并非旨在包罗万象。

另一方面,代码或数据大小很少是个问题。 无法保证无论是编写.5f还是.5,编译器实际上都会存储一个浮点数或一个double。 例如,如果我写“printf(”%g“,3。* 4. + 5。)”,则编译器不需要存储3,4或5.它只需要生成一个写“17的程序” “标准输出,它可以通过存储3,4和5并在运行时进行计算或通过存储17并在运行时将其传递给printf或仅存储字符串”17“并将其写入到带put的标准输出,不存储任何数字或根本不调用printf。

因此,通常,使用哪种类型的重要事项是正确表达您想要执行的计算,而不是担心优化。 如果您编写“foo(.5)”并且foo具有双参数,则编译器可以将.5f存储在程序的常量中并生成代码,在运行时将该.5f加载到双重寄存器并将其传递给foo 。 我希望有一个好的编译器以最小的forms存储常量,可以加载而不需要额外的执行成本。

您还需要考虑0.5在单精度和双精度浮点中都是完全可表示的。 这意味着它们完全相同。 相应格式中可用的有效位数是不重要的,因为值0.5仅需要有效数中的单个位(隐含位),并且所有剩余位都是0。

因此,如果您需要节省存储空间,最好是0.5f。