IEEE754関数

本ページには広告が含まれています。

単精度浮動小数点数、倍精度浮動小数点数の数値をIEEE754形式で表された2進数の文字列に、もしくはIEEE754形式で表された2進数の文字列を単精度浮動小数点数、倍精度浮動小数点数の数値に変換します。

構文
  1. UString = IEEE754.singleToBin( dec )
  2. Double = IEEE754.binToSingle( bin )
  3. UString = IEEE754.doubleToBin( dec )
  4. Double = IEEE754.binToDouble( bin )
引数
dec 必須
10進数
bin 必須
2進数
戻り値

プログラム

UWSC
//////////////////////////////////////////////////
// 【引数】
//   dec : 10進数 
//   bin : 2進数 
// 【戻り値】
//   
//////////////////////////////////////////////////
MODULE IEEE754
	FUNCTION singleTobin(dec)
		DIM s = IIF(dec >= 0, "0", "1")
		DIM integer = decToBin(SPLIT(dec, ".")[0])
		DIM decimal = SPLIT(dec, ".")[1]
		decimal = "0." + decimal
		decimal = decToBin(decimal)
		DIM bin = integer + COPY(decimal, POS(".", decimal))
		bin = leftTrim(bin, "0")
		IF COPY(bin, 1, 1) = "." THEN bin = "0" + bin
		DIM e = POS(".", bin) - POS("1", bin)
		e = e - IIF(e > 0, 1, 0) + 127
		e = decToBin(e)
		e = COPY(e, LENGTH(e) - 8 + 1)
		DIM m = strPad(COPY(leftTrim(REPLACE(bin, ".", ""), "0"), 2, 24), 24, "0", RIGHT)
		DIM keta = 24
		WHILE COPY(m, keta, 1) = "1"
			keta = keta - 1
		WEND
		m = strPad(COPY(leftTrim(REPLACE(bin, ".", ""), "0"), 2, keta - 1), keta - 1, "0", RIGHT) + "1" + strRepeat("0", 24 - keta)
		m = COPY(m, 1, 23)
		RESULT = s + e + m
	FEND
	FUNCTION binToSingle(bin)
		DIM s = IIF(COPY(bin, 1, 1) = 0, 1, -1)
		DIM e = COPY(bin, 2, 8)
		DIM m = COPY(bin, 10)
		e = binToDec(e, FALSE) - 127
		m = "1" + m
		IFB e < 0 THEN
			m = "0." + strRepeat("0", ABS(e+1)) +  m
		ELSE
			m = COPY(m, 1, e + 1) + "." + COPY(m, e + 2)
		ENDIF
		RESULT = s * binToDec(m, FALSE)
	FEND
	FUNCTION doubleToBin(dec, bool = FALSE)
		DIM s = IIF(dec >= 0, "0", "1")
		DIM integer = decToBin(SPLIT(dec, ".")[0])
		DIM decimal = SPLIT(dec, ".")[1]
		decimal = "0." + decimal
		decimal = decToBin(decimal)
		DIM bin = integer + COPY(decimal, POS(".", decimal))
		bin = leftTrim(bin, "0")
		IF COPY(bin, 1, 1) ="." THEN bin = "0" + bin
		DIM e = POS(".", bin) - POS("1", bin)
		e = e - IIF(e > 0, 1, 0) + 1023
		e = decToBin(e)
		e = COPY(e, LENGTH(e) - 11 + 1)
		IFB bool THEN
			DIM m = strPad(COPY(leftTrim(REPLACE(bin, ".", ""), "0"), 2, 53), 53, "0", RIGHT)
			DIM keta = 53
			WHILE COPY(m, keta, 1) = "1"
				keta = keta - 1
			WEND
			m = strPad(COPY(leftTrim(REPLACE(bin, ".", ""), "0"), 2, keta - 1), keta - 1, "0", RIGHT) + "1" + strRepeat("0", 53 - keta)
			m = COPY(m, 1, 52)
		ELSE
			m = strPad(COPY(leftTrim(REPLACE(bin, ".", ""), "0"), 2, 52), 52, "0", RIGHT)
		ENDIF
		RESULT = s + e + m
	FEND
	FUNCTION binToDouble(bin)
		DIM s = IIF(COPY(bin, 1, 1) = 0, 1, -1)
		DIM e = COPY(bin, 2, 11)
		DIM m = COPY(bin, 13)
		e = binToDec(e, FALSE) - 1023
		m = "1" + m
		IFB e < 0 THEN
			m = "0." + strRepeat("0", ABS(e+1)) +  m
		ELSE
			m = COPY(m, 1, e + 1) + "." + COPY(m, e + 2)
		ENDIF
		RESULT = s * binToDec(m, FALSE)
	FEND
ENDMODULE

//////////////////////////////////////////////////
// 【引数】
//   bin : 2進数 
//   signFlg : 符号付きならばTrue 
// 【戻り値】
//   10進数に変換した値 
//////////////////////////////////////////////////
FUNCTION binToDec(bin, signFlg = TRUE)
	DIM dec = 0
	DIM decimalFlg = IIF(POS(".", bin), TRUE, FALSE)
	IFB COPY(bin, 1, 1) = "1" AND signFlg THEN
		DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
		DIM lsb = IIF(decimalFlg, POS(".", bin) - LENGTH(bin), 0)
		DIM dec2 = POWER(2, msb) - 1
		FOR i = -1 TO lsb STEP -1
			dec2 = dec2 + POWER(2, i)
		NEXT
		DIM a = binToDec(bin, FALSE)
		DIM b = dec2
		dec = -1 * (bitXor(a, b) + POWER(2, lsb))
	ELSE
		IFB decimalFlg THEN
			DIM integer = COPY(bin, 1, POS(".", bin) - 1)
			DIM decimal = COPY(bin, POS(".", bin) + 1)
			FOR i = 1 TO LENGTH(decimal)
				dec = dec + COPY(decimal, i, 1) * POWER(2, -1 * i)
			NEXT
		ELSE
			integer = bin
		ENDIF
		FOR i = 1 TO LENGTH(integer)
			dec = dec + COPY(integer, i, 1) * POWER(2, LENGTH(integer) - i)
		NEXT
	ENDIF
	RESULT = dec
FEND

//////////////////////////////////////////////////
// 【引数】
//   arg1 : 数値1(10進数) 
//   arg2 : 数値2(10進数) 
// 【戻り値】
//   2つの数値のビット毎の排他的論理和 
//////////////////////////////////////////////////
FUNCTION bitXor(arg1, arg2)
	DIM args[1] = arg1, arg2
	DIM bins[1]
	DIM decimals[1]
	DIM integers[1]
	DIM keta[1]
	IFB ABS(arg1) <> arg1 OR ABS(arg2) <> arg2 THEN
		RESULT = ERR_VALUE
		EXIT
	ENDIF
	FOR i = 0 TO 1
		bins[i] = decToBin(args[i])
		decimals[i] = 0
		IFB POS(".", bins[i]) <> 0 THEN
			integers[i] = COPY(bins[i], 1, POS(".", bins[i]) - 1)
			decimals[i] = COPY(bins[i], POS(".", bins[i]) + 1)
		ELSE
			integers[i] = bins[i]
		ENDIF
	NEXT
	keta[0] = IIF(LENGTH(integers[0]) > LENGTH(integers[1]), LENGTH(integers[0]), LENGTH(integers[1]))
	integers[0] = strPad(integers[0], keta[0], "0", LEFT)
	integers[1] = strPad(integers[1], keta[0], "0", LEFT)
	keta[1] = IIF(LENGTH(decimals[0]) > LENGTH(decimals[1]), LENGTH(decimals[0]), LENGTH(decimals[1]))
	decimals[0] = strPad(decimals[0], keta[1], "0", RIGHT)
	decimals[1] = strPad(decimals[1], keta[1], "0", RIGHT)
	DIM bin = ""
	FOR i = 1 TO keta[0]
		bin = bin + (VAL(COPY(integers[0], i, 1)) XOR VAL(COPY(integers[1], i, 1)))
	NEXT
	bin = bin + "."
	FOR i = 1 TO keta[1]
		bin = bin + (VAL(COPY(decimals[0], i, 1)) XOR VAL(COPY(decimals[1], i, 1)))
	NEXT
	RESULT = binToDec(bin)
FEND

//////////////////////////////////////////////////
// 【引数】
//   dec : 10進数 
//   signFlg : 符号付きならばTrueを指定 
//   digits : 変換した2進数の桁数合わせを自動で行うかを示すブール値、もしくは桁数を表す数値(8,16,24,32,64のいずれか)を指定 
//   recursive : 再帰処理の深さ。処理する際に必要なだけで指定する必要はありません。 
// 【戻り値】
//   2進数に変換した値 
//////////////////////////////////////////////////
FUNCTION decToBin(dec, signFlg = TRUE, digits = FALSE, recursive = 1)
	IFB dec < 0 AND signFlg = FALSE THEN
		RESULT = ERR_VALUE
		EXIT
	ENDIF
	IFB VARTYPE(digits) <> VAR_BOOLEAN AND digits < CEIL(LOGN(2, ABS(dec))) + IIF(dec < 0, 1, 0) THEN
		RESULT = ERR_VALUE
		EXIT
	ENDIF
	DIM bin = ""
	DIM decimalFlg = IIF(POS(".", dec) <> 0, TRUE, FALSE)
	DIM negativeFlg = IIF(dec < 0, TRUE, FALSE)
	dec = ABS(dec)
	DIM integer = IIF(decimalFlg, COPY(dec, 1, POS(".", dec) - 1), dec)
	DIM offset = POWER(10, LENGTH(dec) - POS(".", dec))
	DIM decimal = IIF(decimalFlg, COPY(dec, POS(".", dec) + 1) / offset, 0)
	REPEAT
		bin = (integer MOD 2) + bin
		integer = INT(integer / 2)
	UNTIL integer = 0
	IFB decimalFlg THEN
		bin = bin + "."
		DIM loop = 0
		REPEAT
			loop = loop + 1
			decimal = decimal * 2
			bin = bin + IIF(decimal >= 1, "1", "0")
			IF decimal > 1 THEN decimal = decimal - 1
		UNTIL decimal = 1 OR loop >= 64
		WHILE loop MOD 4 <> 0
			loop = loop + 1
			bin = bin + "0"
		WEND
	ENDIF
	IFB VARTYPE(digits) = VAR_BOOLEAN THEN
		bin = strPad(bin, CEIL(LENGTH(REPLACE(bin, ".", "")) / 8) * 8, "0", LEFT)
	ELSE
		bin = strPad(bin, digits, "0", LEFT)
	ENDIF
	IFB negativeFlg THEN
		DIM msb = IIF(decimalFlg, POS(".", bin) - 1, LENGTH(bin))
		DIM lsb = IIF(decimalFlg , POS(".", bin) - LENGTH(bin), 0)
		DIM a = binToDec(bin, FALSE)
		DIM b = POWER(2, msb) - 1
		FOR i = -1 TO lsb STEP -1
			b = b + POWER(2, i)
		NEXT
  		dec = bitXor(a, b) + POWER(2, lsb)
 		bin = decToBin(dec, signFlg, digits, recursive + 1)
	ENDIF
	IFB recursive = 1 THEN
		DIM bit = COPY(bin, 1, 1)
 		DIM len = LENGTH(REPLACE(bin, ".", ""))
		IF negativeFlg AND (bit = "0" OR len MOD 2 <> 0) THEN bin = strRepeat("1", IIF(len MOD 2 <> 0, 4, 8)) + bin
		IF !negativeFlg AND signFlg AND (bit = "1" OR len MOD 8 <> 0) THEN bin = strRepeat("0", IIF(len MOD 8 <> 0, 4, 8)) + bin
	ENDIF
	RESULT = bin
FEND

//////////////////////////////////////////////////
// 【引数】
//   expr : 評価する式 
//   truepart : 評価した式がTrueのときに返す値 
//   falsepart : 評価した式がFalseのときに返す値 
// 【戻り値】
//   truepart : 評価した式がTrueのとき、falsepart : 評価した式がFalseのとき 
//////////////////////////////////////////////////
FUNCTION IIF(expr, truepart, falsepart)
	IFB EVAL(expr) THEN
		RESULT = truepart
	ELSE
		RESULT = falsepart
	ENDIF
FEND

//////////////////////////////////////////////////
// 【引数】
//   str : 文字列 
//   characters : 削除する文字、デフォルトでは制御文字を表すASCII文字コードの範囲(\x00..\x1F\x7F)が指定されています。文字の範囲を指定する場合は、開始文字..終了文字の形式で指定。 
// 【戻り値】
//   左側の制御文字もしくは指定された文字が取り除かれた文字列 
//////////////////////////////////////////////////
FUNCTION leftTrim(str, characters = "\x00..\x1F\x7F")
	characters = REPLACE(characters, "-", "\-")
	IF reTest(characters, "\\x[0-9A-Fa-f]{2}\.\.\\x[0-9A-Fa-f]{2}") THEN characters = REPLACE(characters, "..", "-")
	RESULT = reReplace(str, "", "^[" + characters + "]+")
FEND

//////////////////////////////////////////////////
// 【引数】
//   str1 : 置換される文字列 
//   str2 : 置換後の文字列 
//   Pattern : 置換する文字列のパターン 
//   IgnoreCase : 大文字・小文字を区別しない場合はTrue、区別する場合はFalse 
//   Global : 文字列全体を検索する場合はTrue、しない場合はFalse 
// 【戻り値】
//   正規表現置換後の文字列 
//////////////////////////////////////////////////
FUNCTION reReplace(str1, str2, Pattern, IgnoreCase = TRUE, Global = TRUE)
	DIM re = CREATEOLEOBJ("VBScript.RegExp")
	re.Pattern = Pattern
	re.IgnoreCase = IgnoreCase
	re.Global = Global
	RESULT = re.Replace(str1, str2)
FEND

//////////////////////////////////////////////////
// 【引数】
//   str : 正規表現による検索の対象となる文字列 
//   Pattern : 正規表現で使用するパターンを設定 
//   IgnoreCase : 大文字・小文字を区別しない場合はTrue、区別する場合はFalse 
//   Global : 文字列全体を検索する場合はTrue、しない場合はFalse 
// 【戻り値】
//   正規表現にマッチするかどうかを示すブール値 
//////////////////////////////////////////////////
FUNCTION reTest(str, Pattern, IgnoreCase = TRUE, Global = TRUE)
	DIM re = CREATEOLEOBJ("VBScript.RegExp")
	re.Pattern = Pattern
	re.IgnoreCase = IgnoreCase
	re.Global = Global
	RESULT = re.Test(str)
FEND

//////////////////////////////////////////////////
// 【引数】
//   num : 符号を求める数値 
// 【戻り値】
//   1 : 正の数、0 : ゼロ、-1 : 負の数、ERR_VALUE : それ以外 
//////////////////////////////////////////////////
FUNCTION sign(num)
	SELECT TRUE
		CASE !CHKNUM(num)
			RESULT = ERR_VALUE
		CASE num > 0
			RESULT = 1
		CASE num = 0
			RESULT = 0
		CASE num < 0
			RESULT = -1
	SELEND
FEND

//////////////////////////////////////////////////
// 【引数】
//   input : 入力文字列 
//   length : 埋めたあとの長さ 
//   str : 埋める文字 
//   type : 埋める方向 
// 【戻り値】
//   指定文字で埋めた文字列 
//////////////////////////////////////////////////
FUNCTION strPad(input, length, str = " ", type = RIGHT)
	DIM s = ""
	SELECT type
		CASE LEFT
			FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
				s = s + str
			NEXT
			input = COPY(s, 1, length - LENGTH(input)) + input
		CASE RIGHT
			FOR i = 1 TO CEIL((length - LENGTH(input)) / LENGTH(str))
				s = s + str
			NEXT
			input = input + COPY(s, 1, length - LENGTH(input))
	SELEND
	RESULT = input
FEND

//////////////////////////////////////////////////
// 【引数】
//   inputs : 繰り返す文字列 
//   multiplier : inputsを繰り返す回数 
// 【戻り値】
//   inputsをmultiplier回を繰り返した文字列を返します 
//////////////////////////////////////////////////
FUNCTION strRepeat(inputs, multiplier)
	DIM res = ""
	FOR n = 1 TO multiplier
		res = res + inputs
	NEXT
	RESULT = res
FEND

使い方

単精度浮動小数点数の数値をIEEE754形式の2進数の文字列に変換

単精度浮動小数点数をIEEE754形式で表された2進数の文字列に変換します。結果は4バイト(32文字)で返されます。

UWSC
PRINT IEEE754.singleToBin(1.3)
結果
プレーンテキスト
00111111101001100110011001100110

倍精度浮動小数点数の数値をIEEE754形式の2進数の文字列に変換

倍精度浮動小数点数をIEEE754形式で表された2進数の文字列に変換します。結果は8バイト(64文字)で返されます。

UWSC
PRINT IEEE754.doubleToBin(1.3)
結果
プレーンテキスト
0011111111110100110011001100110011001100110011001100110011001100

IEEE754形式の2進数の文字列を単精度浮動小数点数の数値に変換

IEEE754形式で表された2進数の文字列を単精度浮動小数点数の数値に変換します。単精度は4バイトなので32文字で指定します。001111111010011001100110011001101.3を単精度浮動小数点数をIEEE754形式に変換した文字列です。1.3は2進数で表したときに無限小数となり丸め誤差が生じるため精度は落ちます。

UWSC
PRINT IEEE754.binToSingle("00111111101001100110011001100110")
結果
プレーンテキスト
1.29999995231628

IEEE754形式の2進数の文字列を倍精度浮動小数点数の数値に変換

IEEE754形式で表された2進数の文字列を倍精度浮動小数点数の数値に変換します。倍精度は8バイトなので64文字で指定します。

UWSC
PRINT IEEE754.binToDouble("0011111111110100110011001100110011001100110011001100110011001100")
結果
プレーンテキスト
1.3