ObjC получает 64-битное число из потока - PullRequest
1 голос
/ 09 ноября 2010

Я успешно передаю 64-битное число от клиента objC к клиенту java, но не могу отправить клиенту objC.

Код Java / * * Получение двойного (64-битного) номераиз потока.* / private double getDouble () генерирует 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

/*
 * 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];
}

результат NSLog равен


размер long long 8 tempNum: -4616134021117358511 битов -4616134021117358511

число должно быть: -1.012345


Проблема в том, что я пытаюсь преобразовать Java в objC вфункция getDouble.Мое промежуточное программное обеспечение учитывает проблемы порядка байтов.Простое решение, если цель имеет прямой порядок байтов

- (double)getDouble

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

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



return swapped;

Спасибо всем за вклад - получил большой опыт и немного понимания из этого упражнения.

Ответы [ 2 ]

3 голосов
/ 09 ноября 2010

Двойной и длинный длинный не одно и то же. Длинный представляет целое число, которое не имеет дробной части, а двойное представляет число с плавающей запятой, которое имеет дробную часть. Эти два типа имеют совершенно разные способы представления своих значений в памяти. То есть, если бы вы посмотрели на биты long long, представляющие число 4000, и сравнили их с битами для double, представляющего число 4000, они были бы другими.

Итак, как замечает Вева, первым шагом для вас будет использование правильного типа double и правильного средства форматирования% f при вызове NSLog ().

Я бы добавил, однако, что вам также нужно быть осторожным, чтобы ваши байты были в исходном порядке для машины, на которой работает код C. Подробное описание того, что я имею в виду, см. В http://en.wikipedia.org/wiki/Endianness. Короткая версия состоит в том, что разные процессоры могут по-разному представлять числа в памяти, и вы должны убедиться, что в вашем коде, как только вы получите кучу байты из сети, вы устанавливаете байты в правильном порядке для вашего процессора, прежде чем пытаться интерпретировать его как число.

К счастью, это решенная проблема, и ее легко объяснить с помощью функции CFConvertFloat64SwappedToHost () из 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];
0 голосов
/ 09 ноября 2010

Вы, вероятно, хотите преобразовать его в double (возможно / возможно через объединение; см. Комментарий Джонатана) и использовать спецификатор %f.

...