MAX_FLOAT与浮动行为之间不一致

时间:2015-11-30 23:25:19

标签: objective-c

在iOS上,我尝试将数字1448924191存储为NSNumber,然后使用floatValue将其作为浮点数检索:

    double max_float = MAXFLOAT; // really big num (3.4028234663852886E+38)
    double someEpoch = 1448924191;
    NSNumber *epochNum = [NSNumber numberWithDouble:someEpoch]; //

但是,当我要求浮动时,返回是关闭的 - 四舍五入到最近的60个单位间隔:

        float asFloat = [epochNum floatValue];    // 1448924160 - rounded to 60???
        double asDouble = [epochNum doubleValue]; // 1448924191 - correct

使用doubleValue解决了这个问题,但为什么呢?不应该浮点数能够处理这个数字,因为它远远小于FLOAT_MAX吗?

1 个答案:

答案 0 :(得分:1)

正如您对问题的评论中所提到的,这是浮点数的一个基本限制。 iOS上的float是32位浮点数。其中一些位用于存储指数,因此可存储的有效位数远小于int中的位数。

如果您#import <float.h>,您将可以访问许多宏,这些宏将告诉您浮点格式的详细信息,包括:

  

FLT_DIG

     

这是精度的小数位数   浮点数据类型。从技术上讲,如果p和b是精度和基数   (分别)为表示,则小数精度q为   任何浮点数的最大小数位数   q基数为10的数字可以舍入为浮点数   使用p基数b位数然后再返回,而不更改为q小数   位数。

您可以从int转换为float的最大数字中的数字或多或少,而不会丢失任何精度。它实际上是一个保守的估计 - 你可以通过与该标题中的其他宏进行一些计算来计算你可以存储在浮点数中的绝对最大整数,尽管我怀疑它是否会成为你所做的事情。我想做。

说到从int转换为float,你还应该知道在你的例子的这行代码中:

double someEpoch = 1448924191;

您将从整数1448924191隐式转换为双重表示。这样可以正常工作,因为1448924191可以完全表示为double和int。如果使该值大于适合long int的值,则可能会出现奇怪的行为,因为常量将存储为unsigned long,然后转换为double。发生时,编译器至少会警告您这个错误。

如果你想要一个双常数,你应该确保在值中包含一个小数点:

double someEpoch = 1448924191.0;

如果您只是立即将其分配给双变量,那么这一点就不那么重要了,但是如果你曾经#define一个浮点常量,那么添加小数点以确保它得到它是有用的在任何地方使用它作为浮点值。