0

JavaとiPhone/objCクライアント間でデータを送信しています。Javaクライアントには、新しいクライアントのミドルウェアへの統合をテストするために使用している確立されたミドルウェアコンポーネントがあります。

すべてのバイトシフト操作に問題があります。Javaコードは本番環境にあり、変更できません。ダブルが最も広範であるように思われるので、私はそれを投稿します。

objCから送信するには:

-(void)putDouble:(NSNumber *)v{

    unsigned long long n = [v unsignedLongLongValue];

    dataToSend = [NSMutableData data];

    long long i = (int)n & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 8) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 16) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 24) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(n)]];


    i = ((int)n >> 32) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];


    i = ((int)n >> 40) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];


    i = ((int)n >> 48) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];


    i = ((int)n >> 56) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];
    [self send:dataToSend];

}

Javaは以下を受け取ります:

/*
 * 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から[[WVDoublealloc]initWithDouble:-13456.134]を送信すると

javaは2倍になります5.53E-322

Javaは他の開発環境で本番環境にあるため、問題はobjC側にあります。すべての本番クライアントで、-13456.134が変換された結果です。

Javaクライアントが使用するsendDoubleコードは次のとおりです。`

 // Write a double (64-bit) number to the stream.

private void putDouble(double number) throws IOException
{
    long n = Double.doubleToLongBits(number);

    // have to write these in reverse order to be comptible

    stream.write((int)(n) & 0x0ff);
    stream.write((int)((n >>> 8)) & 0x0ff);
    stream.write((int)((n >>> 16)) & 0x0ff);
    stream.write((int)((n >>> 24)) & 0x0ff);
    stream.write((int)((n >>> 32)) & 0x0ff);
    stream.write((int)((n >>> 40)) & 0x0ff);
    stream.write((int)((n >>> 48)) & 0x0ff);
    stream.write((int)((n >>> 56)) & 0x0ff);
}

//--------------------------------------------------------------------------------

`

4

3 に答える 3

3

@Vovaniumが指摘したように、doubleのlong long値を取得しています。これは、例では-13456を返します。分数も指数もありません。

シフトとマスクの操作では、intへのキャストが早すぎます。シフトとマスクの後にキャストを適用する必要があります。また、ループでラップすると、変更するコードの量が減ります。

int i;
int j;

for (j = 0; j < sizeof(n); j++) {
    i = (int)(n >> (j*8)) & 0x0ff;
    [dataToSend appendData:[NSMutableData dataWithBytes:&i length:sizeof(i)]];
}
[self send:dataToSend];

JavaDocs for Doubleによると、Javaはビットが特定の順序になることを想定していることに注意してください。doubleからunsignedlonglongにキャストしてもそのビット順序が生成されない場合、誤った値が取得されます。その場合、送信する前にビットを再配置する必要があるかもしれません。

ビット63(マスク0x8000000000000000Lによって選択されるビット)は、浮動小数点数の符号を表します。ビット62〜52(マスク0x7ff0000000000000Lによって選択されるビット)は指数を表します。ビット51〜0(マスク0x000fffffffffffffLによって選択されるビット)は、浮動小数点数の仮数(仮数と呼ばれることもあります)を表します。

アップデート:

正しいビットセットで作業できるように、@Vovaniumの変更を必ず取得してください。

double nd = [v doubleValue];
unsigned long long n = *(long long *)&nd;

-1.0の値でテストしてみてください。-1.0のIEEE754ビットパターンは次のとおりです。

0xbff0000000000000

そして、シリアル化すると、バイトは次のようになります

00 00 00 00 00 00 f0 bf

代わりに、これらのバイトを取得する場合:

bf f0 00 00 00 00 00 00

エンディアンオーダーの問題が発生しています。その場合は、サンプルコードの行を次のように変更します。

    i = (int)(n >> ((sizeof(n) - j - 1)*8)) & 0x0ff;

これは、longlongがデコードされる順序を逆にするだけです。

于 2010-11-03T15:56:59.317 に答える
2

ObjCコードは、(unsignedLongLongValueによって取得された)long long integerのビットパターンを送信します。これは、Javaコードがdoubleのビットパターンとして解釈しようとします。ULLとしてアクセスする場合、doubleValueを使用してdoubleのビットパターンを取得する必要があります。

double nd = [v doubleValue];
unsigned long long n = *(long long *)&nd;
于 2010-11-03T15:04:51.453 に答える
1

sizeof(n)(8バイト)またはsizeof(i)(4バイト)でデータを送信する場合は、一度に1バイトではなく8バイトまたは4バイトを読み取ることを期待する必要があります。代わりに、一度に1バイトを送信するつもりなので、データ型は1バイト、長さは1にする必要があると思います。

于 2010-11-05T21:50:51.797 に答える