2016-12-22 10 views
3

私はc#で書かれたtcpサーバーを持っています。私は2つのクライアント(C + +とjavascript)を書く必要があります。私は10進数(16byte - 128bit)をc#クライアントでデシリアライズできますが、他の言語を逆シリアル化することはできません。C#10進数からC++へのfloatとjavascript番号

小数点以下は、浮動小数点型または倍精度型を使用できます。

するとシリアル化の進:

MemoryStream combinedMessage = new MemoryStream(); 
decimal d = 2135102.06m; 
using (BinaryWriter writer = new BinaryWriter(combinedMessage, encoding)) 
{ 
    writer.Write(d); 
} 

byte[] message = combinedMessage.ToArray(); 

直列化されたとして:

 62 232 185 12 0 0 0 0 0 0 0 0 0 0 2 0 

私はバイト[] C++でとJavaScriptから小数をデシリアライズするにはどうすればよいですか?

+1

あなたはフロート 'へdecimal''から変換されない理由は、2進浮動小数点値としてそれをデシリアライズするために持っていれば'または' double'最初に?それは他の言語で逆シリアル化する方がはるかに簡単になるはずです... –

+0

私はサーバー側を変更できません –

+3

これは残念です。その場合は、正確なバイナリ形式の10進数のドキュメントを読んで、変換を自分で実装する必要があります。基本的には、整数を最初に取り出してから適切にスケールすることになります。 –

答えて

3

最初の12バイトはリトルエンディアンの96ビット整数で、バイト13と14は未使用(現在)、バイト15はスケール(10の累乗で除算)を含み、バイト16は符号ビット(他のビットは未使用)。主な難しさは正確な変換にあります。十進数が「あまりにも大きくない」場合でも、それをfloatまたはNumberに変換することは、精度が多かれ少なかれ低下するように行うことができます。

以下のルーチンは、小数点以下を変換する最も正確な方法ではなく、最速のものではありませんが、精度や速度にあまり関心がなければ、仕事を完了することができますほとんどのC言語のようなものに簡単に翻訳できます。ここでは、JavaScriptである:

var b = [ 62, 232, 185, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 ]; 

var d = 0.0; 
for (var i = 11; i >= 0; --i) { 
    var k = b[i]; 
    for (var j = 0; j != 8; ++j) { 
     d *= 2; 
     d += (k & 0x80) >> 7; 
     k <<= 1; 
    } 
} 
var scale = b[14]; 
d /= Math.pow(10, scale); 
if (b[15] >= 0x80) d = -d; 

これは、すでにほとんどの有効なC#です。あなたが変更する必要があるのはMath.Powbyte[] b = { 62 ... }です。 C(および拡張C++による)のために変更がはるかに複雑ではありません。

#include <math.h> 

unsigned char b[] = { 62, 232, 185, 12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0 }; 

double d = 0.0; 
for (int i = 11; i >= 0; --i) { 
    unsigned char k = b[i]; 
    for (int j = 0; j != 8; ++j) { 
     d *= 2; 
     d += (k & 0x80) >> 7; 
     k <<= 1; 
    } 
} 
int scale = b[14]; 
d /= pow(10, scale); 
if (b[15] >= 0x80) d = -d; 
+0

thats、ありがとうございました –

+0

@CihanT:以前の反復から残ったバイト数をスキップするコードでかなり重大なバグを修正しました。 –

関連する問題