【问题标题】:iPhone/Obj C: Why does convert float to int: (int) float * 100 does not work?iPhone/Obj C:为什么将 float 转换为 int: (int) float * 100 不起作用?
【发布时间】:2011-06-11 06:01:43
【问题描述】:

在我的代码中,我使用浮点数进行货币计算,但四舍五入产生了不希望的结果,因此我试图将其全部转换为 int。在我的 init 函数中,尽可能少地改变基础设施,我这样做了:

-(id)initWithPrice:(float)p;
{
[self setPrice:(int)(p*100)];
}

我在主要部分乘以 100 b/c,数值以 .xx 到 2 位小数给出。我异常地注意到,对于 float 1.18,int 将其四舍五入为 117。有人知道它会这样做吗?浮动将其保留为 1.18。我预计 int equiv 为 118 美分。

谢谢。

【问题讨论】:

  • 如果可能的话,我会尝试使用 NSDecimalNumber 而不是浮点数来存储货币值。

标签: iphone objective-c floating-point int


【解决方案1】:

浮点数总是有点不精确。使用 IEEE 浮点编码,可以精确地表示 2 的幂 (如 4,2,1,0.5,0.25,0.125,0.0625,...) ,但像 0.1 这样的数字始终是近似值(只​​需尝试将其表示为总和2) 的幂。

您的 (int) 强制转换将截断任何进来的内容,因此如果 p*100 由于这种不精确而解析为 117.9999995,那么它将变为 1.17 而不是 1.18。

更好的解决方案是在 p*100 上使用类似 roundf 的东西。如果您可以上游并在整个程序中使用整数完全转换为定点数学,那就更好了。

【讨论】:

  • 或者简而言之:永远不要在处理金钱时使用floatdoublelong double。永远。
  • 阿门!除非您故意偏向四舍五入,以便将增量存入您自己的银行账户。
  • 好的。谢谢。它不是 117.99999999995 因为在我的代码中,init 是这样的: Item *item = [[Item alloc] initWithPrice:1.18] 当我为 float 版本和 int 版本执行 NSLog(%f, %i) 时,我得到 1.18 的浮点数和 117 的整数。我在这里对 cme​​ts 投了赞成票,但从技术上讲,这不是答案。如果有人有答案,我会这样标记。
  • @Yko:您实际上还没有确定“它不是 117.99999999995”。如果数据类型不能表示该数字,您编写“1.18”这一事实并不重要,并且执行NSLog(@"%f", 1.18) 不会告诉您任何有用的信息,因为它会四舍五入。请改为NSLog(@"%1.20f", 1.18),它会显示真实号码。
  • @Yko:查克是对的。试试这个:将 1.18 插入 digitconvert.com 以查看它的二进制和十六进制。现在复制十六进制值,重新打开 digitconvert.com,然后将十六进制值粘贴到十六进制存储桶中。十进制数是 1.17999999 ......所以十六进制和二进制值不是一个精确的表示,至少有 56 位尾数。无论您添加多少位,这可能都是正确的。这与尝试将 1/3 表示为 0.33333 相同......无论添加多少位,您都永远不会到达那里。这就是您的程序中正在发生的事情。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-10-12
  • 2019-12-04
  • 2011-08-09
  • 2017-09-04
  • 2011-11-02
  • 2012-05-05
  • 1970-01-01
相关资源
最近更新 更多