将十六进制字符串转换为IEEE 754浮点数

时间:2014-05-02 02:39:43

标签: objective-c nsstring hex cgfloat

我正在尝试将带有十六进制值的nsstring转换为浮点值。

NSString *hexString = @"3f9d70a4";

浮点值应为= 1.230

我试图解决这个问题的一些方法是:

1.NSScanner

-(unsigned int)strfloatvalue:(NSString *)str
{
   float outVal;
   NSString *newStr = [NSString stringWithFormat:@"0x%@",str];
   NSScanner* scanner = [NSScanner scannerWithString:newStr];
   NSLog(@"string %@",newStr);
   bool test = [scanner scanHexFloat:&outVal];
   NSLog(@"scanner result %d = %a (or %f)",test,outVal,outVal);
   return outVal;
}

结果:

 string 0x3f9d70a4
 scanner result 1 = 0x1.fceb86p+29 (or 1067282624.000000)

2.广播指针

NSNumber * xPtr = [NSNumber numberWithFloat:[(NSNumber *)@"3f9d70a4" floatValue]];

结果:3.000000

3 个答案:

答案 0 :(得分:3)

你所拥有的不是“十六进制浮点数”,由%a字符串格式生成并由scanHexFloat:扫描,但是是32位浮点值的十六进制表示 - 即实际位。

要将其转换回C中的浮点,需要弄乱类型系统 - 让您访问构成浮点值的字节。您可以使用union

执行此操作
typedef union { float f; uint32_t i; } FloatInt;

此类型与struct类似,但字段重叠在一起。您应该明白,进行这种操作需要您了解存储格式,了解字节顺序等。不要轻易做到这一点。

现在您具有上述类型,您可以扫描十六进制整数并将结果字节解释为浮点数:

FloatInt fl;
NSScanner *scanner = [NSScanner scannerWithString:@"3f9d70a4"];

if([scanner scanHexInt:&fl.i])        // scan into the i field
{
    NSLog(@"%x -> %f", fl.i, fl.f);   // display the f field, interpreting the bytes of i as a float
}
else
{
    // parse error
}

这很有效,但请再仔细考虑一下你在做什么。

HTH

答案 1 :(得分:1)

我认为更好的解决方案是这样的解决方法:

-(float) getFloat:(NSInteger*)pIndex
{
    NSInteger index = *pIndex;
    NSData* data = [self subDataFromIndex:&index withLength:4];
    *pIndex = index;
    uint32_t hostData = CFSwapInt32BigToHost(*(const uint32_t *)[data bytes]);
    return  *(float *)(&hostData);;
}

你的参数是一个NSData,它以十六进制格式表示数字,输入参数是一个指向NSData元素的指针。

答案 2 :(得分:0)

因此,基本上,您正在尝试使C的NSString成为float,这是一种古老的方式!

NSString* hexString = @"3f9d70a4";
const char* cHexString = [hexString UTF8String];
long l = strtol(cHexString, NULL, 16);
float f = *((float *) &l);
// f = 1.23

有关更多详细信息,请参见this answer