


商品スタッフII
ニャンコロさんのVB用ルーチンをJavaに移植したものです(単精度のみ)。
詳細はhttp://homepage3.nifty.com/buckybecky/sw/ms2ieee.htmをどうぞ。
import org.junit.*;
/**
* 古いマイクロソフト浮動小数点形式との変換。現在floatのみ、doubleは未サポート。
*
* 参考資料:http://homepage3.nifty.com/buckybecky/sw/ms2ieee.htm
* 上記サイトより:
* MS Binary 形式とは、N88NASIC 等、初期の Microsoft Basic の浮動小数点数の
* フォーマット。Quick Basic や Visual Basic の浮動小数点数は IEEE 形式とのこと。
*
*/
public class MSBinFloat {
/**
* 4バイトのMS Binary形式単精度浮動小数点バイト列を(javaの)floatに変換する。
* 入力バイトの順序はlittle Endian
*/
public static float msbinToFloat(byte[]_msbin) {
int[]msbin = new int[4];
for (int i = 0; i < 4; i++) {
msbin[i] = (int)_msbin[i] & 0xff;
}
int expo = msbin[3] - 2;
if (expo < 0) {
return 0;
}
int sign = msbin[2] & 0x80;
int ieee0 = msbin[0];
int ieee1 = msbin[1];
int ieee2 = ((expo & 1) * 128) | (msbin[2] & 0x7f);
int ieee3 = sign | (expo / 2);
return Float.intBitsToFloat(
(ieee3 << 24) + (ieee2 << 16) + (ieee1 << 8) + ieee0
);
}
/**
* (javaの)floatをMS Binary形式単精度浮動小数点数バイト列(4バイト)に変換する。
* 出力バイトの順序はLittle Endian
*/
public static byte[]floatToMsbin(float value) {
int intBits = Float.floatToIntBits(value);
int ieee0 = (intBits >> 0) & 0xff;
int ieee1 = (intBits >> 8) & 0xff;
int ieee2 = (intBits >> 16) & 0xff;
int ieee3 = (intBits >> 24) & 0xff;
int sign = ieee3 & 0x80;
int expo = ((ieee3 & 0x7f) * 2) | (ieee2 / 128);
if (expo > 0) {
expo += 2;
}
if (expo <= 0xff) {
return new byte[] {
(byte)ieee0,
(byte)ieee1,
(byte)((ieee2 & 0x7f) | sign),
(byte)expo,
};
}
return new byte[] {
(byte)0xff,
(byte)0xff,
(byte)(0x7f | sign),
(byte)0xff,
};
}
/////////////////////////////////////////////////////////////////////////////
// 以下はJUnitを使用したテスト
/////////////////////////////////////////////////////////////////////////////
private static class TestFloat {
/** float値 */
float value;
/** MS Binary形式バイト列 */
byte[]bytes;
private TestFloat(float value, byte[]bytes) {
this.value = value;
this.bytes = bytes;
}
}
/** 値とバイト配列のサンプル */
private static TestFloat[]testFloats = new TestFloat[] {
new TestFloat(350F, new byte[] { 0x00, 0x00, 0x2f, (byte)0x89 }),
new TestFloat(94500F, new byte[] { 0x00, (byte)0x92, 0x38, (byte)0x91 }),
new TestFloat(2100F, new byte[] { 0x00, 0x40, 0x03, (byte)0x8c }),
new TestFloat(2200F, new byte[] { 0x00, (byte)0x80, 0x09, (byte)0x8c }),
};
@Test
public void test() {
for (TestFloat testFloat: testFloats) {
float value = msbinToFloat(testFloat.bytes);
Assert.assertEquals(testFloat.value, value);
}
for (TestFloat testFloat: testFloats) {
byte[]bytes = floatToMsbin(testFloat.value);
Assert.assertArrayEquals(testFloat.bytes, bytes);
}
}
}
|