所以我刚刚在我的代码中发现了这个错误,我想知道我不理解的规则。
我有一个float
变量logDiff,目前包含一个非常小的数字。我想看看它是否大于常数表达式(第12位的80%)。我多年前在代码完成中阅读过,只是将计算常量保留为最简单的形式以便于阅读,而编译器(XCode 4.6.3)无论如何都会内联它们。我有,
if ( logDiff > 1/12 * .8 ) {
我假设.8并且分数都评估为正确的数字。看起来合法:
(lldb) expr (float) 1/12 * .8
(double) $1 = 0.0666666686534882
(lldb) expr logDiff
(float) $2 = 0.000328541
但它始终错误地评估为true。即使我把周围的东西弄得乱七八糟。
(lldb) expr logDiff > 1/12 * .8
(bool) $4 = true
(lldb) expr logDiff > (1/12 * .8)
(bool) $5 = true
(lldb) expr logDiff > (float)(1/12 * .8)
(bool) $6 = true
我发现我必须明确拼写其中至少一个作为花车以获得正确的结果,
(lldb) expr logDiff > (1.f/12.f * .8f)
(bool) $7 = false
(lldb) expr logDiff > (1/12.f * .8)
(bool) $8 = false
(lldb) expr logDiff > (1./12 * .8f)
(bool) $11 = false
(lldb) expr logDiff > (1./12 * .8)
(bool) $12 = false
但我最近阅读a popular style guide明确地避开了这些更高级的数字文字,显然是根据我的假设,编译器会比我聪明并且做我的意思。
如果他们可能需要成为浮点数,我是否应该像1.f
一样拼写我的数字常量?听起来很迷信。帮助我理解为什么以及什么时候需要?
答案 0 :(得分:4)
表达式1/12
是整数除法。这意味着结果将被截断为零。
执行(float) 1/12
时,将其作为浮点数转换,整个表达式成为浮点表达式。
答案 1 :(得分:1)
在C int/int
中提供int
。如果你没有明确地告诉编译器将至少一个转换为float,它将进行除法并向下舍入到最近的int(在这种情况下为0)。
我注意到链接样式指南实际上是说除非必要,否则避免将数字设为特定类型。在这种情况下,您需要的是编译器进行某些类型转换所需的内容
答案 2 :(得分:1)
1 / 4
之类的表达式被视为整数除法,因此没有小数精度。在这种特定情况下,结果将是0
。您可以将此视为int / int
隐含int
。
我是否总是将我的数字常量拼写为1.f,如果它们可能需要浮点数?听起来很迷信。帮助我理解为什么以及什么时候需要?
这不是迷信,你告诉编译器这些是类型文字(浮动作为一个例子),编译器将处理它们上的所有操作。
此外,你可以施放一个表达式。请考虑以下事项:
float result = ( float ) 1 / 4;
...我正在将1
投射为浮点数,因此float / int
的结果将为float
。请参阅数据类型操作优先级(或促销)。
答案 3 :(得分:1)
这很简单。默认情况下,数字值被视为int
。
有数学表达的地方并不重要。但是如果出现分歧,它会让你发疯。 (int) 1 / (int) 12
不是(float) 0.08333
,而是(int) 0
。
1/12.0
将评估为(float) 0.83333
。
旁注:当你再使用int时浮动,然后再有一个陷阱等着你。那是你比较平等的价值的时候。
float f = 12/12.0f;
if (f = 1) ... // this may not work out. Never expect a float to be of a specific value. They can vary slightly.
更好的是:
if (abs(f - 1) < 0.0001) ... // this way yoru comparison is fuzzy enough for the variances that float values may come with.