开发者

ObjC getting 64 bit number from stream

I am successfully passing a 64 bit number from a objC client to a java client, but am unable to send to an objC client.

Java Code /* * Retrieve a double (64-bit) number from the stream. */ private double getDouble() throws IOException { byte[] buffer = getBytes(8);

    long bits =
            ((long)buffer[0] & 0x0ff) |
            (((long)buffer[1] & 0x0ff) << 8) |
            (((long)buffer[2] & 0x0ff) << 16) |
            (((long)buffer[3] & 0x0ff) << 24) |
            (((long)buffer[4] & 0x0ff) << 32) |
            (((long)buffer[5] & 0x0ff) << 40) |
            (((long)buffer[开发者_如何学运维6] & 0x0ff) << 48) |
            (((long)buffer[7] & 0x0ff) << 56);

    return Double.longBitsToDouble(bits);
}

objC code

/*
 * Retrieve a double (64-bit) number from the stream.
 */
- (double)getDouble
{
    NSRange dblRange = NSMakeRange(0, 8);
    char buffer[8];

    [stream getBytes:buffer length:8];
    [stream replaceBytesInRange:dblRange withBytes:NULL length:0];

    long long bits =
    ((long long)buffer[0] & 0x0ff) |
    (((long long)buffer[1] & 0x0ff) << 8) |
    (((long long)buffer[2] & 0x0ff) << 16) |
    (((long long)buffer[3] & 0x0ff) << 24) |
    (((long long)buffer[4] & 0x0ff) << 32) |
    (((long long)buffer[5] & 0x0ff) << 40) |
    (((long long)buffer[6] & 0x0ff) << 48) |
    (((long long)buffer[7] & 0x0ff) << 56);

    NSNumber *tempNum = [NSNumber numberWithLongLong:bits];
    NSLog(@"\n***********\nsizeof long long %d \n tempNum: %@\nbits %lld",sizeof(long long), tempNum, bits);
    return [tempNum doubleValue];
}

the result of NSLog is


sizeof long long 8 tempNum: -4616134021117358511 bits -4616134021117358511

the number should be : -1.012345


The problem is that I am trying to convert Java to objC in the getDouble func. My middleware takes into account the endian issues. The simple solution is if the target is little endian

- (double)getDouble

NSRange dblRange = NSMakeRange(0, 8);
double swapped;

[stream getBytes:&swapped length:8];
[stream replaceBytesInRange:dblRange withBytes:NULL length:0];



return swapped;

Thanks all for input - got a lot of experience and a little understanding from this exercise.


A double and a long long are not the same thing. A long represents an integer, which has no fractional portion, and a double represents a floating-point number, which has a fractional portion. These two types have completely different ways of representing their values in memory. That is to say, if you were to look at the bits for a long long representing the number 4000 and compare those to the bits for a double representing the number 4000, they would be different.

So as Wevah notes, the first step is for you to use the proper double type, and the correct %f formatter in your call to NSLog().

I would add, though, that you also need to be careful to get your bytes in the native order for the machine your C code is running on. For a detailed description of what I'm referring to, see http://en.wikipedia.org/wiki/Endianness The short version is that different processors may represent numbers in different ways in memory, and you need to ensure in your code that once you get a pile of bytes from the network, you are putting the bytes in the right order for your processor before you attempt to interpret it as a number.

Luckily, this is a solved issue, and is easily accounted for by using the CFConvertFloat64SwappedToHost() function from CoreFoundation:

[stream getBytes:buffer length:8];
[stream replaceBytesInRange:dblRange withBytes:NULL length:0];

double myDouble = CFConvertFloat64SwappedToHost(*((double*)buffer));
NSNumber *tempNum = [NSNumber numberWithDouble:myDouble];
NSLog(@"\n***********\nsizeof double %d \n tempNum: %@\nbits %f",sizeof(double), tempNum, myDouble);
return [tempNum doubleValue];


You probably want to convert it to a double (possibly/probably via a union; see Jonathan's comment) and use the %f specifier.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜