この回答は、Number.MAX_SAFE_INTEGER
(または2**53-1
)と2**31
の間の絶対値で整数をアドレス指定しようとします。現在のソリューションは32ビット以内の符号付き整数のみを扱いますが、このソリューションはfloat64ToInt64Binary()
を使用して64ビットの2の補数形式で出力します。
// IIFE to scope internal variables
var float64ToInt64Binary = (function () {
// create union
var flt64 = new Float64Array(1)
var uint16 = new Uint16Array(flt64.buffer)
// 2**53-1
var MAX_SAFE = 9007199254740991
// 2**31
var MAX_INT32 = 2147483648
function uint16ToBinary() {
var bin64 = ''
// generate padded binary string a Word at a time
for (var Word = 0; Word < 4; Word++) {
bin64 = uint16[Word].toString(2).padStart(16, 0) + bin64
}
return bin64
}
return function float64ToInt64Binary(number) {
// NaN would pass through Math.abs(number) > MAX_SAFE
if (!(Math.abs(number) <= MAX_SAFE)) {
throw new RangeError('Absolute value must be less than 2**53')
}
var sign = number < 0 ? 1 : 0
// shortcut using other answer for sufficiently small range
if (Math.abs(number) <= MAX_INT32) {
return (number >>> 0).toString(2).padStart(64, sign)
}
// little endian byte ordering
flt64[0] = number
// subtract bias from exponent bits
var exponent = ((uint16[3] & 0x7FF0) >> 4) - 1022
// encode implicit leading bit of mantissa
uint16[3] |= 0x10
// clear exponent and sign bit
uint16[3] &= 0x1F
// check sign bit
if (sign === 1) {
// apply two's complement
uint16[0] ^= 0xFFFF
uint16[1] ^= 0xFFFF
uint16[2] ^= 0xFFFF
uint16[3] ^= 0xFFFF
// propagate carry bit
for (var Word = 0; Word < 3 && uint16[Word] === 0xFFFF; Word++) {
// apply integer overflow
uint16[Word] = 0
}
// complete increment
uint16[Word]++
}
// only keep integer part of mantissa
var bin64 = uint16ToBinary().substr(11, Math.max(exponent, 0))
// sign-extend binary string
return bin64.padStart(64, sign)
}
})()
console.log('8')
console.log(float64ToInt64Binary(8))
console.log('-8')
console.log(float64ToInt64Binary(-8))
console.log('2**33-1')
console.log(float64ToInt64Binary(2**33-1))
console.log('-(2**33-1)')
console.log(float64ToInt64Binary(-(2**33-1)))
console.log('2**53-1')
console.log(float64ToInt64Binary(2**53-1))
console.log('-(2**53-1)')
console.log(float64ToInt64Binary(-(2**53-1)))
console.log('2**52')
console.log(float64ToInt64Binary(2**52))
console.log('-(2**52)')
console.log(float64ToInt64Binary(-(2**52)))
console.log('2**52+1')
console.log(float64ToInt64Binary(2**52+1))
console.log('-(2**52+1)')
console.log(float64ToInt64Binary(-(2**52+1)))
.as-console-wrapper {
max-height: 100% !important;
}
この回答では、 IEEE-754倍精度浮動小数点形式 を重点的に扱います。
seee eeee eeee ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff ffff
---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ---- ----
[ uint16[3] ] [ uint16[2] ] [ uint16[1] ] [ uint16[0] ]
[ flt64[0] ]
little endian byte ordering
s = sign = uint16[3] >> 15
e = exponent = (uint16[3] & 0x7FF) >> 4
f = fraction
このソリューションのしくみは、64ビット浮動小数点数と符号なし16ビット整数配列の間にリトルエンディアンのバイト順で結合することです。整数入力範囲を検証した後、入力をバッファ上の倍精度浮動小数点数にキャストしてから、共用体を使用して値へのビットアクセスを取得し、不偏バイナリ指数と小数ビットに基づいてバイナリ文字列を計算します。
このソリューションは純粋なECMAScript 5で実装されていますが、 String#padStart()
を使用する点が異なります。これには ここで利用可能なpolyfillがあります 。
function dec2bin(dec){
return (dec >>> 0).toString(2);
}
dec2bin(1); // 1
dec2bin(-1); // 11111111111111111111111111111111
dec2bin(256); // 100000000
dec2bin(-256); // 11111111111111111111111100000000
あなたは Number.toString(2)
関数を使うことができますが、負の数を表すときにはいくつか問題があります。たとえば、(-1).toString(2)
の出力は"-1"
です。
この問題を解決するには、符号なし右シフトビット演算子( >>>
)を使用して、自分の数値を符号なし整数に変換します。
(-1 >>> 0).toString(2)
を実行すると、あなたの数を0ビット右にシフトします。それは数自体を変えることはありませんが、それは符号なし整数として表されます。上記のコードは"11111111111111111111111111111111"
を正しく出力します。
この質問 にはさらに説明があります。
-3 >>> 0
(右論理シフト)は、引数を符号なし整数に強制変換します。これが、32ビットの2の補数表現である-3を取得する理由です。
注1:この回答は引数として数値を期待しているので、それに応じて変換します。
Note 2:結果は、の先頭になしの文字列なので、必要に応じてパディングを適用します。
やってみる
num.toString(2);
2は基数で、2から36までの任意の基数にすることができます。
ソース はこちら
アップデート:
これは正数に対してのみ機能します。Javascriptは負の2進整数を2の補数表記で表します。私はトリックをするべきであるこの小さな機能を作った、私はそれをきちんとテストしていない:
function dec2Bin(dec)
{
if(dec >= 0) {
return dec.toString(2);
}
else {
/* Here you could represent the number in 2s compliment but this is not what
JS uses as its not sure how many bits are in your number range. There are
some suggestions https://stackoverflow.com/questions/10936600/javascript-decimal-to-binary-64-bit
*/
return (~dec).toString(2);
}
}
私は ここから助けを得ました
「バイナリに変換」のバイナリは、主に3つのことを指すことができます。位置番号システム、メモリ内のバイナリ表現、または32ビットのビット文字列。 (64ビットのビット文字列については、 Patrick Robertsの回答 を参照)
1.ナンバーシステム
(123456).toString(2)
は、数値を基数2 の定位置系 に変換します。このシステムでは、負数は10進数と同じようにマイナス記号で書かれます。
2.内部表現
数値の内部表現は 64ビット浮動小数点 であり、いくつかの制限がこの答えで説明されています。 簡単な方法はありません JavaScriptでこれのビット文字列表現を作成したり、特定のビットにアクセスすることはできません。
3.マスクとビット演算子
MDNはビットごとの演算子がどのように機能するかについて 概要 を示しています。重要なこと
ビット演算子は、それらのオペランドを 32ビット のシーケンス(0と1)として扱います。
演算が適用される前に、64ビットの浮動小数点数は32ビットの符号付き整数にキャストされます。彼らは戻って変換された後。
これは、数値を32ビット文字列に変換するためのMDNコード例です。
function createBinaryString (nMask) {
// nMask must be between -2147483648 and 2147483647
for (var nFlag = 0, nShifted = nMask, sMask = ""; nFlag < 32;
nFlag++, sMask += String(nShifted >>> 31), nShifted <<= 1);
return sMask;
}
createBinaryString(0) //-> "00000000000000000000000000000000"
createBinaryString(123) //-> "00000000000000000000000001111011"
createBinaryString(-1) //-> "11111111111111111111111111111111"
createBinaryString(-1123456) //-> "11111111111011101101101110000000"
createBinaryString(0x7fffffff) //-> "01111111111111111111111111111111"
簡単な方法はただ...
Number(42).toString(2);
// "101010"
注意 - xが正である場合、基本的な(x>>>0).toString(2);
はわずかな問題を抱えています。私は私の答えの最後に、まだ>>>を使用しながら>>>メソッドに関するその問題を修正するいくつかのサンプルコードを持っています。
(-3>>>0).toString(2);
prints -3 in 2s complement.
1111111111101
実用的な例
C:\>type n1.js
console.log( (-3 >>> 0).toString(2) );
C:\>
C:\>node n1.js
11111111111111111111111111111101
C:\>
URLバーのこれは別の簡単な証明です
javascript:alert((-3>>>0).toString(2))
注 - 結果は常に1から始まるという点で非常にわずかに欠陥があります。負の数の場合、これは問題ありません。正の数の場合は、結果が実際に2の補数になるように、先頭に0を追加する必要があります。そのため、(8>>>0).toString(2)
は1000を生成しますが、実際には2の補数の8の倍数ではありませんが、その0の前に01000を付けると、2の補数の8の倍数になります。適切な2の補数では、0で始まるビット列は> = 0で、1で始まるビット列は負です。
例えばこれはその問題を回避します
// or x=-5 whatever number you want to view in binary
x=5;
if(x>0) prepend="0"; else prepend="";
alert(prepend+((x>>>0)).toString(2));
他の解決策はAnnanからのもの(Annanの説明と定義はエラーでいっぱいですが、彼は正しい出力を生成するコードを持っています)、そしてPatrickからの解決策です。
2の補数で0から始まる正の数および1から始まる負の数の事実を理解していない人は、2の補数でこのSO QnAをチェックできます。 「2の補数」とは何ですか?
あなたはビットの配列を返すあなた自身の関数を書くことができます。数値をビットに変換する方法の例
上記の行の例:2 * 4 = 8、剰余は1なので9 = 1 0 0 1
function numToBit(num){
var number = num
var result = []
while(number >= 1 ){
result.unshift(Math.floor(number%2))
number = number/2
}
return result
}
残りを下から上に読みます。真ん中の1桁目を上にします。
別のアプローチを使用して、これを行うものを思い付きました。私は自分のプロジェクトでこのコードを使用しないことにしましたが、誰かに役立つ場合に備えて、適切な場所に残しておくと思いました。
function intToBitString(input, size, unsigned) {
if ([8, 16, 32].indexOf(size) == -1) {
throw "invalid params";
}
var min = unsigned ? 0 : - (2 ** size / 2);
var limit = unsigned ? 2 ** size : 2 ** size / 2;
if (!Number.isInteger(input) || input < min || input >= limit) {
throw "out of range or not an int";
}
if (!unsigned) {
input += limit;
}
var binary = input.toString(2).replace(/^-/, '');
return binary.padStart(size, '0');
}
function bitStringToInt(input, size, unsigned) {
if ([8, 16, 32].indexOf(size) == -1) {
throw "invalid params";
}
input = parseInt(input, 2);
if (!unsigned) {
input -= 2 ** size / 2;
}
return input;
}
// EXAMPLES
var res;
console.log("(uint8)10");
res = intToBitString(10, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");
console.log("(uint8)127");
res = intToBitString(127, 8, true);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");
console.log("(int8)127");
res = intToBitString(127, 8, false);
console.log("intToBitString(res, 8, false)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, false));
console.log("---");
console.log("(int8)-128");
res = intToBitString(-128, 8, false);
console.log("intToBitString(res, 8, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 8, true));
console.log("---");
console.log("(uint16)5000");
res = intToBitString(5000, 16, true);
console.log("intToBitString(res, 16, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 16, true));
console.log("---");
console.log("(uint32)5000");
res = intToBitString(5000, 32, true);
console.log("intToBitString(res, 32, true)");
console.log(res);
console.log("reverse:", bitStringToInt(res, 32, true));
console.log("---");