Javascript Word To Binary to Array of Bits - javascript

I have this code // Fiddle : https://jsfiddle.net/7buscnhw/
// Word to bits func
function dec2bin(dec) {
return (dec >>> 0).toString(2);
}
// binary to bit array
function bin2array(bin) {
let Bitarr = []
for(let i = 0; i < bin.length; ++i)
Bitarr[i] = (bin >> i) & 1;
return Bitarr;
}
R24011 = dec2bin(10);
Bits = bin2array(R24011);
msg = {
R24011: R24011,
BitArray: Bits
}
console.log(msg)
It correctly outputs 1010 for Ten in binary, but when I push it to an array I get [0,1,0,0]
I'm sure it'll be something stupid but I cant figure out what I've done wrong.

You pass bin (which is a string "1010") and apply >> to it, which makes Javascript convert it to a number in base 10, resulting in 1010 (one thousand and ten), which is binary 1111110010. Then, you convert that one to binary once again, using only four bits and in reversed order, which results in [0,1,0,0]
If you want to convert a number (not a string) to an array bits (and avoid built-ins), you can do that like this:
function num2bits(number) {
let Bitarr = []
while (number) {
Bitarr.unshift(number & 1);
number >>= 1
}
return Bitarr;
}
console.log(num2bits(10))
With built-ins this is as simple as
bits = [...yourNumber.toString(2)].map(Number)

You can directly use spread syntax to convert the binary string to an array.
function dec2bin(dec) {
return (dec >>> 0).toString(2);
}
function bin2array(bin) {
return [...bin].map(Number);
}
R24011 = dec2bin(10);
console.log(R24011)
Bits = bin2array(R24011);
console.log(Bits)

Related

Java script convert number to string base two

I am doing a test and the task is to write a function that takes an integer as input, and returns the number of bits that are equal to one in the binary representation of that number. You can guarantee that input is non-negative.
So i have the following problem : while my code runs ok for the most part and passes all tests when the inputs are 9843520790 and 8989787640 I am getting wrong results. So I hoped in the calc and made this numbers binary and tried couple of console.log(bNum) and what I noticed is that I loose the high byte during the conversion. Meaning that after bNum=(n>>>0).toString(2); the console.log(bNum) returns 11001001100011110010110101110011 for 7676570995 when it should return 111001001100011110010110101110011.
var countBits = function(n) {
let bNum=(n>>>0).toString(2);//converts int to base 2
console.log(bNum);
let sum=0;
for(let i=0;i<=bNum.length-1;i++)
{
if(bNum[i]==1)
sum+=1;
}
return sum;
};
I am not asking for a coding solution just someone to explain why this is happening so I can find a wayto fix it.Thanks in advance :)
I think your issue is n>>>0. I not to familiar with the >>>0 but as far as I know it converts the input to a 32bit unsigned in. The max value for an uint is 4294967295 so those numbers exceed it. Therefore I think some information is lost in the conversion.
var countBitsOld = function(n) {
let bNum=(n>>>0).toString(2);//converts int to base 2
let sum=0;
for(let i=0;i<=bNum.length-1;i++)
{
if(bNum[i]==1)
sum+=1;
}
return sum;
};
var countBitsNew = function(n) {
let bNum=(n).toString(2);//converts int to base 2
let sum=0;
for(let i=0;i<=bNum.length-1;i++)
{
if(bNum[i]==1)
sum+=1;
}
return sum;
};
const test = (n) => console.log({old: countBitsOld(n), new: countBitsNew(n)});
test(9843520790);
test(8989787640);
test(76765709950);
.

Byte array to Hex string conversion in javascript

I have a byte array of the form [4,-101,122,-41,-30,23,-28,3,..] which I want to convert in the form 6d69f597b217fa333246c2c8
I'm using below function
function toHexString(bytes) {
return bytes.map(function(byte) {
return (byte & 0xFF).toString(16)
}).join('')
}
which is giving me a string of the same form but I suspect that it's not an efficient conversion because the hex string is bit shorter than expected. I think translating should get "0a10a6dc".
Please tell me if I'm wrong or is this a right conversion but maybe I'm not using the right byte array
byte array 4,-127,45,126,58,-104,41,-27,-43,27,-35,100,-50,-77,93,-16,96,105,-101,-63,48,-105,49,-67,110,111,26,84,67,-89,-7,-50,10,-12,56,47,-49,-42,-11,-8,-96,-117,-78,97,-105,9,-62,-44,-97,-73,113,96,23,112,-14,-62,103,-104,90,-14,117,78,31,-116,-7
Corresponding conversion 4812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ceaf4382fcfd6f5f8a08bb261979c2d49fb771601770f2c267985af2754e1f8cf9
You are missing the padding in the hex conversion. You'll want to use
function toHexString(byteArray) {
return Array.from(byteArray, function(byte) {
return ('0' + (byte & 0xFF).toString(16)).slice(-2);
}).join('')
}
so that each byte transforms to exactly two hex digits. Your expected output would be 04812d7e3a9829e5d51bdd64ceb35df060699bc1309731bd6e6f1a5443a7f9ce0af4382fcfd6f5f8a08bb2619709c2d49fb771601770f2c267985af2754e1f8cf9
Using map() won't work if the input is of a type like Uint8Array: the result of map() is also Uint8Array which can't hold the results of string conversion.
function toHexString(byteArray) {
var s = '0x';
byteArray.forEach(function(byte) {
s += ('0' + (byte & 0xFF).toString(16)).slice(-2);
});
return s;
}
A more concise and performant (see https://jsperf.com/byte-array-to-hex-string) alternative using Array.reduce():
function toHexString(byteArray) {
return byteArray.reduce((output, elem) =>
(output + ('0' + elem.toString(16)).slice(-2)),
'');
}
(Also without "& 0xFF" because in my opinion if an array is passed in that contains values larger than 255, the output should be messed up, so that the user can more easily see that their input was wrong.)
Since this is the first Google hit for "js byte to hex" and I needed some time to understand the function of Bergi, I rewrote the function and added some comments that made it easier for me to understand:
function byteToHex(byte) {
// convert the possibly signed byte (-128 to 127) to an unsigned byte (0 to 255).
// if you know, that you only deal with unsigned bytes (Uint8Array), you can omit this line
const unsignedByte = byte & 0xff;
// If the number can be represented with only 4 bits (0-15),
// the hexadecimal representation of this number is only one char (0-9, a-f).
if (unsignedByte < 16) {
return '0' + unsignedByte.toString(16);
} else {
return unsignedByte.toString(16);
}
}
// bytes is an typed array (Int8Array or Uint8Array)
function toHexString(bytes) {
// Since the .map() method is not available for typed arrays,
// we will convert the typed array to an array using Array.from().
return Array.from(bytes)
.map(byte => byteToHex(byte))
.join('');
}
For more information about the const unsignedByte = byte & 0xff-part, check What does AND 0xFF do?.
Array.from is not available in every browser (e.g. not in IE11), check How to convert a JavaScript Typed Array into a JavaScript Array for more information
The OP forgot to add the leading 0 for numbers that can be displayed with only 4 bits.
All of the previous solutions work but they all require the creation of many strings and concatenation and slicing of the created strings. I got thinking there has to be a better way to go about it now that there are typed arrays. I originally did this using node and then commented out the lines that use Buffer and changed them to TypedArrays so it would work in a browser too.
It's more code but it's significantly faster, at least in the quick jsperf (no longer working) I put together. The string manipulation version in the accepted answer performed 37000 ops/sec while the code below managed 317000 ops/sec. There is a lot of hidden overhead in creating string objects.
function toHexString (byteArray) {
//const chars = new Buffer(byteArray.length * 2);
const chars = new Uint8Array(byteArray.length * 2);
const alpha = 'a'.charCodeAt(0) - 10;
const digit = '0'.charCodeAt(0);
let p = 0;
for (let i = 0; i < byteArray.length; i++) {
let nibble = byteArray[i] >>> 4;
chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit;
nibble = byteArray[i] & 0xF;
chars[p++] = nibble > 9 ? nibble + alpha : nibble + digit;
}
//return chars.toString('utf8');
return String.fromCharCode.apply(null, chars);
}
IMHO, A simpler solution with Typescript:
const convertHashToHex = (value: TypedArray | number[]) : string => {
return value.map(v => v.toString(16).padStart(2, '0')).join('');
}
JS version:
const convertHashToHex = (value) => {
return value.map(v => v.toString(16).padStart(2, '0')).join('');
}
You need to pad the hex conversion with the appropriate number of leading zeroes.
When converting a byte array to a hex array, we have to consider how they can be signed numbers. If so, we gotta convert them to decimal numbers first. signed numbers to decimal conversion. Then, we can use the .toString(16) method to convert it to hex.
const hexArr = byteArr.map((byte) => {
if (byte < 0) {
byte = -((byte ^ 0xff) + 1); //converting 2s complement to a decimal number
}
//add padding at the start to ensure it's always 2 characters long otherwise '01' will be '1'
return byte.toString(16).padStart(2, '0');
});
This is cross-browser solution for ArrayBuffer:
function buf2hex(buffer) {
var u = new Uint8Array(buffer),
a = new Array(u.length),
i = u.length;
while (i--) // map to hex
a[i] = (u[i] < 16 ? '0' : '') + u[i].toString(16);
u = null; // free memory
return a.join('');
};
If running on Nodejs
just use Buffer.toString('base64')
crypto.randomBytes(byteLength).toString('base64')

parseInt not converting decimal to binary?

From my understanding the binary number system uses as set of two numbers, 0's and 1's to perform calculations.
Why does:
console.log(parseInt("11", 2)); return 3 and not 00001011?
http://www.binaryhexconverter.com/decimal-to-binary-converter
Use toString() instead of parseInt:
11..toString(2)
var str = "11";
var bin = (+str).toString(2);
console.log(bin)
According JavaScript's Documentation:
The following examples all return NaN:
parseInt("546", 2); // Digits are not valid for binary representations
parseInt(number, base) returns decimal value of a number presented by number parameter in base base.
And 11 is binary equivalent of 3 in decimal number system.
var a = {};
window.addEventListener('input', function(e){
a[e.target.name] = e.target.value;
console.clear();
console.log( parseInt(a.number, a.base) );
}, false);
<input name='number' placeholder='number' value='1010'>
<input name='base' placeholder='base' size=3 value='2'>
As stated in the documentation for parseInt: The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
So, it is doing exactly what it should do: converting a binary value of 11 to an integer value of 3.
If you are trying to convert an integer value of 11 to a binary value than you need to use the Number.toString method:
console.log(11..toString(2)); // 1011
.toString(2) works when applied to a Number type.
255.toString(2) // syntax error
"255".toString(2); // 255
var n=255;
n.toString(2); // 11111111
// or in short
Number(255).toString(2) // 11111111
// or use two dots so that the compiler does
// mistake with the decimal place as in 250.x
255..toString(2) // 11111111
The parseInt() function parses a string argument and returns an integer of the specified radix (the base in mathematical numeral systems).
So you are telling the system you want to convert 11 as binary to an decimal.
Specifically to the website you are referring, if you look closer it is actually using JS to issue a HTTP GET to convert it on web server side. Something like following:
http://www.binaryhexconverter.com/hesapla.php?fonksiyon=dec2bin&deger=11&pad=false
The shortes method I've found for converting a decimal string into a binary is:
const input = "54654";
const output = (input*1).toString(2);
print(output);
I think you should understand the math behind decimal to binary conversion. Here is the simple implementation in javascript.
main();
function main() {
let input = 12;
let result = decimalToBinary(input);
console.log(result);
}
function decimalToBinary(input) {
let base = 2;
let inputNumber = input;
let quotient = 0;
let remainderArray = [];
let resultArray = [];
if (inputNumber) {
while (inputNumber) {
quotient = parseInt(inputNumber / base);
remainderArray.push(inputNumber % base);
inputNumber = quotient;
}
for (let i = remainderArray.length - 1; i >= 0; i--) {
resultArray.push(remainderArray[i]);
}
return parseInt(resultArray.join(''));
} else {
return `${input} is not a valid input`;
}
}
This is an old question, however I have another solution that might contribute a little bit. I usually use this function to convert a decimal number into a binary:
function dec2bin(dec) {
return (dec >>> 0).toString(2);
}
The dec >>> 0 converts the number into a byte and then toString(radix) function is called to return a binary string. It is simple and clean.
Note: a radix is used for representing a numeric value. Must be an integer between 2 and 36. For example:
2 - The number will show as a binary value
8 - The number will show as an octal value
16 - The number will show as an hexadecimal value
function num(n){
return Number(n.toString(2));
}
console.log(num(5));
This worked for me: parseInt(Number, original_base).toString(final_base)
Eg: parseInt(32, 10).toString(2) for decimal to binary conversion.
Source: https://www.w3resource.com/javascript-exercises/javascript-math-exercise-3.php
Here is a concise recursive version of a manual decimal to binary algorithm:
Divide decimal number in half and aggregate remainder per operation until value==0 and print concatenated binary string
Example using 25: 25/2 = 12(r1)/2 = 6(r0)/2 = 3(r0)/2 = 1(r1)/2 = 0(r1) => 10011 => reverse => 11001
function convertDecToBin(input){
return Array.from(recursiveImpl(input)).reverse().join(""); //convert string to array to use prototype reverse method as bits read right to left
function recursiveImpl(quotient){
const nextQuotient = Math.floor(quotient / 2); //divide subsequent quotient by 2 and take lower limit integer (if fractional)
const remainder = ""+quotient % 2; //use modulus for remainder and convert to string
return nextQuotient===0?remainder:remainder + recursiveImpl(nextQuotient); //if next quotient is evaluated to 0 then return the base case remainder else the remainder concatenated to value of next recursive call
}
}
To get better understanding, I think you should try to do the math of that conversion by yourself.
(1) 11 / 2 = 5
(1) 5 / 2 = 2
(0) 2 / 2 = 1
(1) 1 / 2 = 0
I made a function based on that logic
function decimalToBinary(inputNum) {
let binary = [];
while (inputNum > 0) {
if (inputNum % 2 === 1) {
binary.splice(0,0,1);
inputNum = (inputNum - 1) / 2;
} else {
binary.splice(0,0,0);
inputNum /= 2;
}
}
binary = binary.join('');
console.log(binary);
}
This is what I did to get the solution:
function addBinary(a,b) {
// function that converts decimal to binary
function dec2bin(dec) {
return (dec >>> 0).toString(2);
}
var sum = a+b; // add the two numbers together
return sum.toString(2); //converts sum to binary
}
addBinary(2, 3);
I first converted the decimal number to binary like it said, and I got the function from w3schools under the JavaScript Bitwise lesson. Then to make it easier on myself, I created the variable "sum" which does the addition and finally, I made the addBinary function return the sum as a binary code, then called it. It passed in CodeWars. I hope this makes sense and it helps you.
Just use Number(x).toString(base). Where base needs to be equals 2.
var num1=13;
Number(num1).toString(2)
result: "1101"
Number(11).toString(2)
result: "1011"
It seems like the conversion with the string radix (dec >>> 0).toString(2) is returning the binary number formatted in the wrong direction. I have validated this solution in Chrome. In case anyone wants to manually calculate binary for validation, from left to right you add the numbers together that correspond to a 1 position in your binary number mapping to [1][2][4][8][16][32][64][128] ....
For example:
10 in binary is 0101 OR 0 + 2 + 0 + 8.
13 in binary is 1011 OR 1 + 0 + 4 + 8.
255 in binary is 11111111 OR 1 + 2 + 4 + 8 + 16 + 32 + 64 + 128
function dec2bin(dec){
return (dec >>> 0).toString(2).split('').reverse().join('');
}
This will give the decimal to binary:
let num = "1234"
console.log(num.toString(2));
This will give binary to decimal:
let num = "10011010010";
console.log(parseInt(num, 2));

Int (or short) to byte array using Big endian

I'm trying to make universal functions to convert integers, shorts and others to byte arrays and vice versa, all using pre-defined byte count per value.
The encoding function seems to be correct. It looks like this:
/**Parameters:
data - string, every `bytes` bytes will form one number entry
array - the output array refference where numbers will be put
bytes - number of bytes per entry
big_endian - use big endian? (little endian otherwise)
*/
function fromBytes(data, array, bytes, big_endian) {
//Temporary variable for current number
var num;
//Loop through byte array
for(var i=0, l=data.length; i<l; i+=bytes) {
num=0;
//Jump through the `bytes` and add them to number
if(big_endian) {
for(var b=0; b<bytes; b++) {
num+=(num << 8)+data.charCodeAt(i+b);
}
}
else {
for(var b=bytes-1; b>=0; b--) {
num+=(num << 8)+data.charCodeAt(i+b);
}
}
//Add decomposed number to an array
array.push(num);
}
return array;
}
If there is something wrong please tell me.
Now, the encoding function seems easy for little endian - I just take number%255 and then divide the number by 255 (and repeat that).
But I'm not sure how to encode number in big endian - how to get the largest part first?
Here's my function with the missing part:
/**Parameters:
array - arrau of numbers to encode
bytes - number of bytes per entry
big_endian - use big endian? (little endian otherwise)
*/
function toBytes(array, bytes, big_endian) {
//The produced string
var data = "";
//last retrieved number
var num;
//Loop through byte array
for(var i=0, l=array.length; i<l; i++) {
num = array[i];
if(big_endian) {
/** ??? **/
}
else {
for(var b=bytes-1; b>=0; b--) {
data+=String.fromCharCode(num%255);
num = Math.floor(num/255);
}
}
//Add decomposed number to an array
array.push(num);
}
return array;
}
The little endian conversion works. Could you give me a clue how to encode int, short or double to 4, 2 or 8 bytes using Big endian?

Generate random string/characters in JavaScript

I want a 5 character string composed of characters picked randomly from the set [a-zA-Z0-9].
What's the best way to do this with JavaScript?
I think this will work for you:
function makeid(length) {
let result = '';
const characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
const charactersLength = characters.length;
let counter = 0;
while (counter < length) {
result += characters.charAt(Math.floor(Math.random() * charactersLength));
counter += 1;
}
return result;
}
console.log(makeid(5));
//Can change 7 to 2 for longer results.
let r = (Math.random() + 1).toString(36).substring(7);
console.log("random", r);
Note: The above algorithm has the following weaknesses:
It will generate anywhere between 0 and 6 characters due to the fact that trailing zeros get removed when stringifying floating points.
It depends deeply on the algorithm used to stringify floating point numbers, which is horrifically complex. (See the paper "How to Print Floating-Point Numbers Accurately".)
Math.random() may produce predictable ("random-looking" but not really random) output depending on the implementation. The resulting string is not suitable when you need to guarantee uniqueness or unpredictability.
Even if it produced 6 uniformly random, unpredictable characters, you can expect to see a duplicate after generating only about 50,000 strings, due to the birthday paradox. (sqrt(36^6) = 46656)
Math.random is bad for this kind of thing
server side
Use node crypto module -
var crypto = require("crypto");
var id = crypto.randomBytes(20).toString('hex');
// "bb5dc8842ca31d4603d6aa11448d1654"
The resulting string will be twice as long as the random bytes you generate; each byte encoded to hex is 2 characters. 20 bytes will be 40 characters of hex.
client side
Use the browser's crypto module, crypto.getRandomValues -
The crypto.getRandomValues() method lets you get cryptographically strong random values. The array given as the parameter is filled with random numbers (random in its cryptographic meaning).
// dec2hex :: Integer -> String
// i.e. 0-255 -> '00'-'ff'
function dec2hex (dec) {
return dec.toString(16).padStart(2, "0")
}
// generateId :: Integer -> String
function generateId (len) {
var arr = new Uint8Array((len || 40) / 2)
window.crypto.getRandomValues(arr)
return Array.from(arr, dec2hex).join('')
}
console.log(generateId())
// "82defcf324571e70b0521d79cce2bf3fffccd69"
console.log(generateId(20))
// "c1a050a4cd1556948d41"
A step-by-step console example -
> var arr = new Uint8Array(4) # make array of 4 bytes (values 0-255)
> arr
Uint8Array(4) [ 0, 0, 0, 0 ]
> window.crypto
Crypto { subtle: SubtleCrypto }
> window.crypto.getRandomValues()
TypeError: Crypto.getRandomValues requires at least 1 argument, but only 0 were passed
> window.crypto.getRandomValues(arr)
Uint8Array(4) [ 235, 229, 94, 228 ]
For IE11 support you can use -
(window.crypto || window.msCrypto).getRandomValues(arr)
For browser coverage see https://caniuse.com/#feat=getrandomvalues
client side (old browsers)
If you must support old browsers, consider something like uuid -
const uuid = require("uuid");
const id = uuid.v4();
// "110ec58a-a0f2-4ac4-8393-c866d813b8d1"
Short, easy and reliable
Returns exactly 5 random characters, as opposed to some of the top rated answers found here.
Math.random().toString(36).slice(2, 7);
Here's an improvement on doubletap's excellent answer. The original has two drawbacks which are addressed here:
First, as others have mentioned, it has a small probability of producing short strings or even an empty string (if the random number is 0), which may break your application. Here is a solution:
(Math.random().toString(36)+'00000000000000000').slice(2, N+2)
Second, both the original and the solution above limit the string size N to 16 characters. The following will return a string of size N for any N (but note that using N > 16 will not increase the randomness or decrease the probability of collisions):
Array(N+1).join((Math.random().toString(36)+'00000000000000000').slice(2, 18)).slice(0, N)
Explanation:
Pick a random number in the range [0,1), i.e. between 0 (inclusive) and 1 (exclusive).
Convert the number to a base-36 string, i.e. using characters 0-9 and a-z.
Pad with zeros (solves the first issue).
Slice off the leading '0.' prefix and extra padding zeros.
Repeat the string enough times to have at least N characters in it (by Joining empty strings with the shorter random string used as the delimiter).
Slice exactly N characters from the string.
Further thoughts:
This solution does not use uppercase letters, but in almost all cases (no pun intended) it does not matter.
The maximum string length at N = 16 in the original answer is measured in Chrome. In Firefox it's N = 11. But as explained, the second solution is about supporting any requested string length, not about adding randomness, so it doesn't make much of a difference.
All returned strings have an equal probability of being returned, at least as far as the results returned by Math.random() are evenly distributed (this is not cryptographic-strength randomness, in any case).
Not all possible strings of size N may be returned. In the second solution this is obvious (since the smaller string is simply being duplicated), but also in the original answer this is true since in the conversion to base-36 the last few bits may not be part of the original random bits. Specifically, if you look at the result of Math.random().toString(36), you'll notice the last character is not evenly distributed. Again, in almost all cases it does not matter, but we slice the final string from the beginning rather than the end of the random string so that short strings (e.g. N=1) aren't affected.
Update:
Here are a couple other functional-style one-liners I came up with. They differ from the solution above in that:
They use an explicit arbitrary alphabet (more generic, and suitable to the original question which asked for both uppercase and lowercase letters).
All strings of length N have an equal probability of being returned (i.e. strings contain no repetitions).
They are based on a map function, rather than the toString(36) trick, which makes them more straightforward and easy to understand.
So, say your alphabet of choice is
var s = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
Then these two are equivalent to each other, so you can pick whichever is more intuitive to you:
Array(N).join().split(',').map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
and
Array.apply(null, Array(N)).map(function() { return s.charAt(Math.floor(Math.random() * s.length)); }).join('');
Edit:
I seems like qubyte and Martijn de Milliano came up with solutions similar to the latter (kudos!), which I somehow missed. Since they don't look as short at a glance, I'll leave it here anyway in case someone really wants a one-liner :-)
Also, replaced 'new Array' with 'Array' in all solutions to shave off a few more bytes.
The most compact solution, because slice is shorter than substring. Subtracting from the end of the string allows to avoid floating point symbol generated by the random function:
Math.random().toString(36).slice(-5);
or even
(+new Date).toString(36).slice(-5);
Update: Added one more approach using btoa method:
btoa(Math.random()).slice(0, 5);
btoa(+new Date).slice(-7, -2);
btoa(+new Date).substr(-7, 5);
// Using Math.random and Base 36:
console.log(Math.random().toString(36).slice(-5));
// Using new Date and Base 36:
console.log((+new Date).toString(36).slice(-5));
// Using Math.random and Base 64 (btoa):
console.log(btoa(Math.random()).slice(0, 5));
// Using new Date and Base 64 (btoa):
console.log(btoa(+new Date).slice(-7, -2));
console.log(btoa(+new Date).substr(-7, 5));
A newer version with es6 spread operator:
[...Array(30)].map(() => Math.random().toString(36)[2]).join('')
The 30 is an arbitrary number, you can pick any token length you want
The 36 is the maximum radix number you can pass to numeric.toString(), which means all numbers and a-z lowercase letters
The 2 is used to pick the 3rd index from the random string which looks like this: "0.mfbiohx64i", we could take any index after 0.
Something like this should work
function randomString(len, charSet) {
charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var randomString = '';
for (var i = 0; i < len; i++) {
var randomPoz = Math.floor(Math.random() * charSet.length);
randomString += charSet.substring(randomPoz,randomPoz+1);
}
return randomString;
}
Call with default charset [a-zA-Z0-9] or send in your own:
var randomValue = randomString(5);
var randomValue = randomString(5, 'PICKCHARSFROMTHISSET');
function randomstring(L) {
var s = '';
var randomchar = function() {
var n = Math.floor(Math.random() * 62);
if (n < 10) return n; //1-10
if (n < 36) return String.fromCharCode(n + 55); //A-Z
return String.fromCharCode(n + 61); //a-z
}
while (s.length < L) s += randomchar();
return s;
}
console.log(randomstring(5));
Random String Generator (Alpha-Numeric | Alpha | Numeric)
/**
* Pseudo-random string generator
* http://stackoverflow.com/a/27872144/383904
* Default: return a random alpha-numeric string
*
* #param {Integer} len Desired length
* #param {String} an Optional (alphanumeric), "a" (alpha), "n" (numeric)
* #return {String}
*/
function randomString(len, an) {
an = an && an.toLowerCase();
var str = "",
i = 0,
min = an == "a" ? 10 : 0,
max = an == "n" ? 10 : 62;
for (; i++ < len;) {
var r = Math.random() * (max - min) + min << 0;
str += String.fromCharCode(r += r > 9 ? r < 36 ? 55 : 61 : 48);
}
return str;
}
console.log(randomString(10)); // i.e: "4Z8iNQag9v"
console.log(randomString(10, "a")); // i.e: "aUkZuHNcWw"
console.log(randomString(10, "n")); // i.e: "9055739230"
While the above uses additional checks for the desired A/N, A, N output,
let's break it down the to the essentials (Alpha-Numeric only) for a better understanding:
Create a function that accepts an argument (desired length of the random String result)
Create an empty string like var str = ""; to concatenate random characters
Inside a loop create a rand index number from 0 to 61 (0..9+A..Z+a..z = 62)
Create a conditional logic to Adjust/fix rand (since it's 0..61) incrementing it by some number (see examples below) to get back the right CharCode number and the related Character.
Inside the loop concatenate to str a String.fromCharCode( incremented rand )
Let's picture the ASCII Character table ranges:
_____0....9______A..........Z______a..........z___________ Character
| 10 | | 26 | | 26 | Tot = 62 characters
48....57 65..........90 97..........122 CharCode ranges
Math.floor( Math.random * 62 ) gives a range from 0..61 (what we need).
Let's fix the random to get the correct charCode ranges:
| rand | charCode | (0..61)rand += fix = charCode ranges |
------+----------+----------+--------------------------------+-----------------+
0..9 | 0..9 | 48..57 | rand += 48 = 48..57 |
A..Z | 10..35 | 65..90 | rand += 55 /* 90-35 = 55 */ = 65..90 |
a..z | 36..61 | 97..122 | rand += 61 /* 122-61 = 61 */ = 97..122 |
The conditional operation logic from the table above:
rand += rand>9 ? ( rand<36 ? 55 : 61 ) : 48 ;
// rand += true ? ( true ? 55 else 61 ) else 48 ;
From the explanation above, here's the resulting alpha-numeric snippet:
function randomString(len) {
var str = ""; // String result
for (var i = 0; i < len; i++) { // Loop `len` times
var rand = Math.floor(Math.random() * 62); // random: 0..61
var charCode = rand += rand > 9 ? (rand < 36 ? 55 : 61) : 48; // Get correct charCode
str += String.fromCharCode(charCode); // add Character to str
}
return str; // After all loops are done, return the concatenated string
}
console.log(randomString(10)); // i.e: "7GL9F0ne6t"
Or if you will:
const randomString = (n, r='') => {
while (n--) r += String.fromCharCode((r=Math.random()*62|0, r+=r>9?(r<36?55:61):48));
return r;
};
console.log(randomString(10))
To meet requirement [a-zA-Z0-9] and length of 5 characters, use
For Browser:
btoa(Math.random().toString()).substring(10,15);
For NodeJS:
Buffer.from(Math.random().toString()).toString("base64").substring(10,15);
Lowercase letters, uppercase letters, and numbers will occur.
(it's typescript compatible)
The simplest way is:
(new Date%9e6).toString(36)
This generate random strings of 5 characters based on the current time. Example output is 4mtxj or 4mv90 or 4mwp1
The problem with this is that if you call it two times on the same second, it will generate the same string.
The safer way is:
(0|Math.random()*9e6).toString(36)
This will generate a random string of 4 or 5 characters, always diferent. Example output is like 30jzm or 1r591 or 4su1a
In both ways the first part generate a random number. The .toString(36) part cast the number to a base36 (alphadecimal) representation of it.
Here are some easy one liners. Change new Array(5) to set the length.
Including 0-9a-z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36);})
Including 0-9a-zA-Z
new Array(5).join().replace(/(.|$)/g, function(){return ((Math.random()*36)|0).toString(36)[Math.random()<.5?"toString":"toUpperCase"]();});
Codegolfed for ES6 (0-9a-z)
Array(5).fill().map(n=>(Math.random()*36|0).toString(36)).join('')
I know everyone has got it right already, but i felt like having a go at this one in the most lightweight way possible(light on code, not CPU):
function rand(length, current) {
current = current ? current : '';
return length ? rand(--length, "0123456789ABCDEFGHIJKLMNOPQRSTUVWXTZabcdefghiklmnopqrstuvwxyz".charAt(Math.floor(Math.random() * 60)) + current) : current;
}
console.log(rand(5));
It takes a bit of time to wrap your head around, but I think it really shows how awesome javascript's syntax is.
Generate a secure random alphanumeric Base-62 string:
function generateUID(length)
{
return window.btoa(String.fromCharCode(...window.crypto.getRandomValues(new Uint8Array(length * 2)))).replace(/[+/]/g, "").substring(0, length);
}
console.log(generateUID(22)); // "yFg3Upv2cE9cKOXd7hHwWp"
console.log(generateUID(5)); // "YQGzP"
There is no best way to do this. You can do it any way you prefer, as long as the result suits your requirements. To illustrate, I've created many different examples, all which should provide the same end-result
Most other answers on this page ignore the upper-case character requirement.
Here is my fastest solution and most readable. It basically does the same as the accepted solution, except it is a bit faster.
function readableRandomStringMaker(length) {
for (var s=''; s.length < length; s += 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'.charAt(Math.random()*62|0));
return s;
}
console.log(readableRandomStringMaker(length));
// e3cbN
Here is a compact, recursive version which is much less readable:
const compactRandomStringMaker = (length) => length-- && "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0) + (compactRandomStringMaker(length)||"");
console.log(compactRandomStringMaker(5));
// DVudj
A more compact one-liner:
Array(5).fill().map(()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62)).join("")
// 12oEZ
A variation of the above:
" ".replaceAll(" ",()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62))
The most compact one-liner, but inefficient and unreadable - it adds random characters and removes illegal characters until length is l:
((l,f=(p='')=>p.length<l?f(p+String.fromCharCode(Math.random()*123).replace(/[^a-z0-9]/i,'')):p)=>f())(5)
A cryptographically secure version, which is wasting entropy for compactness, and is a waste regardless because the generated string is so short:
[...crypto.getRandomValues(new Uint8Array(999))].map((c)=>String.fromCharCode(c).replace(/[^a-z0-9]/i,'')).join("").substr(0,5)
// 8fzPq
Or, without the length-argument it is even shorter:
((f=(p='')=>p.length<5?f(p+String.fromCharCode(Math.random()*123).replace(/[^a-z0-9]/i,'')):p)=>f())()
// EV6c9
Then a bit more challenging - using a nameless recursive arrow function:
((l,s=((l)=>l--&&"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0)+(s(l)||""))) => s(l))(5);
// qzal4
This is a "magic" variable which provides a random character every time you access it:
const c = new class { [Symbol.toPrimitive]() { return "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0) } };
console.log(c+c+c+c+c);
// AgMnz
A simpler variant of the above:
const c=()=>"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789".charAt(Math.random()*62|0);
c()+c()+c()+c()+c();
// 6Qadw
In case anyone is interested in a one-liner (although not formatted as such for your convenience) that allocates the memory at once (but note that for small strings it really does not matter) here is how to do it:
Array.apply(0, Array(5)).map(function() {
return (function(charset){
return charset.charAt(Math.floor(Math.random() * charset.length))
}('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789'));
}).join('')
You can replace 5 by the length of the string you want. Thanks to #AriyaHidayat in this post for the solution to the map function not working on the sparse array created by Array(5).
If you are using Lodash or Underscore, then it so simple:
var randomVal = _.sample('ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789', 5).join('');
const c = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
const s = [...Array(5)].map(_ => c[~~(Math.random()*c.length)]).join('')
Here's the method I created.
It will create a string containing both uppercase and lowercase characters.
In addition I've included the function that will created an alphanumeric string too.
Working examples:
http://jsfiddle.net/greatbigmassive/vhsxs/ (alpha only)
http://jsfiddle.net/greatbigmassive/PJwg8/ (alphanumeric)
function randString(x){
var s = "";
while(s.length<x&&x>0){
var r = Math.random();
s+= String.fromCharCode(Math.floor(r*26) + (r>0.5?97:65));
}
return s;
}
Upgrade July 2015
This does the same thing but makes more sense and includes all letters.
var s = "";
while(s.length<x&&x>0){
v = Math.random()<0.5?32:0;
s += String.fromCharCode(Math.round(Math.random()*((122-v)-(97-v))+(97-v)));
}
One liner:
Array(15).fill(null).map(() => Math.random().toString(36).substr(2)).join('')
// Outputs: 0h61cbpw96y83qtnunwme5lxk1i70a6o5r5lckfcyh1dl9fffydcfxddd69ada9tu9jvqdx864xj1ul3wtfztmh2oz2vs3mv6ej0fe58ho1cftkjcuyl2lfkmxlwua83ibotxqc4guyuvrvtf60naob26t6swzpil
Improved #Andrew's answer above :
Array.from({ length : 1 }, () => Math.random().toString(36)[2]).join('');
Base 36 conversion of the random number is inconsistent, so selecting a single indice fixes that. You can change the length for a string with the exact length desired.
Assuming you use underscorejs it's possible to elegantly generate random string in just two lines:
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var random = _.sample(possible, 5).join('');
function randomString (strLength, charSet) {
var result = [];
strLength = strLength || 5;
charSet = charSet || 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
while (strLength--) { // (note, fixed typo)
result.push(charSet.charAt(Math.floor(Math.random() * charSet.length)));
}
return result.join('');
}
This is as clean as it will get. It is fast too, http://jsperf.com/ay-random-string.
Fast and improved algorithm. Does not guarantee uniform (see comments).
function getRandomId(length) {
if (!length) {
return '';
}
const possible =
'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
let array;
if ('Uint8Array' in self && 'crypto' in self && length <= 65536) {
array = new Uint8Array(length);
self.crypto.getRandomValues(array);
} else {
array = new Array(length);
for (let i = 0; i < length; i++) {
array[i] = Math.floor(Math.random() * 62);
}
}
let result = '';
for (let i = 0; i < length; i++) {
result += possible.charAt(array[i] % 62);
}
return result;
}
How about this compact little trick?
var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
var stringLength = 5;
function pickRandom() {
return possible[Math.floor(Math.random() * possible.length)];
}
var randomString = Array.apply(null, Array(stringLength)).map(pickRandom).join('');
You need the Array.apply there to trick the empty array into being an array of undefineds.
If you're coding for ES2015, then building the array is a little simpler:
var randomString = Array.from({ length: stringLength }, pickRandom).join('');
You can loop through an array of items and recursively add them to a string variable, for instance if you wanted a random DNA sequence:
function randomDNA(len) {
len = len || 100
var nuc = new Array("A", "T", "C", "G")
var i = 0
var n = 0
s = ''
while (i <= len - 1) {
n = Math.floor(Math.random() * 4)
s += nuc[n]
i++
}
return s
}
console.log(randomDNA(5));
Case Insensitive Alphanumeric Chars:
function randStr(len) {
let s = '';
while (s.length < len) s += Math.random().toString(36).substr(2, len - s.length);
return s;
}
// usage
console.log(randStr(50));
The benefit of this function is that you can get different length random string and it ensures the length of the string.
Case Sensitive All Chars:
function randStr(len) {
let s = '';
while (len--) s += String.fromCodePoint(Math.floor(Math.random() * (126 - 33) + 33));
return s;
}
// usage
console.log(randStr(50));
Custom Chars
function randStr(len, chars='abc123') {
let s = '';
while (len--) s += chars[Math.floor(Math.random() * chars.length)];
return s;
}
// usage
console.log(randStr(50));
console.log(randStr(50, 'abc'));
console.log(randStr(50, 'aab')); // more a than b
The problem with responses to "I need random strings" questions (in whatever language) is practically every solution uses a flawed primary specification of string length. The questions themselves rarely reveal why the random strings are needed, but I would challenge you rarely need random strings of length, say 8. What you invariably need is some number of unique strings, for example, to use as identifiers for some purpose.
There are two leading ways to get strictly unique strings: deterministically (which is not random) and store/compare (which is onerous). What do we do? We give up the ghost. We go with probabilistic uniqueness instead. That is, we accept that there is some (however small) risk that our strings won't be unique. This is where understanding collision probability and entropy are helpful.
So I'll rephrase the invariable need as needing some number of strings with a small risk of repeat. As a concrete example, let's say you want to generate a potential of 5 million IDs. You don't want to store and compare each new string, and you want them to be random, so you accept some risk of repeat. As example, let's say a risk of less than 1 in a trillion chance of repeat. So what length of string do you need? Well, that question is underspecified as it depends on the characters used. But more importantly, it's misguided. What you need is a specification of the entropy of the strings, not their length. Entropy can be directly related to the probability of a repeat in some number of strings. String length can't.
And this is where a library like EntropyString can help. To generate random IDs that have less than 1 in a trillion chance of repeat in 5 million strings using entropy-string:
import {Random, Entropy} from 'entropy-string'
const random = new Random()
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
"44hTNghjNHGGRHqH9"
entropy-string uses a character set with 32 characters by default. There are other predefined characters sets, and you can specify your own characters as well. For example, generating IDs with the same entropy as above but using hex characters:
import {Random, Entropy, charSet16} from './entropy-string'
const random = new Random(charSet16)
const bits = Entropy.bits(5e6, 1e12)
const string = random.string(bits)
"27b33372ade513715481f"
Note the difference in string length due to the difference in total number of characters in the character set used. The risk of repeat in the specified number of potential strings is the same. The string lengths are not. And best of all, the risk of repeat and the potential number of strings is explicit. No more guessing with string length.
One-liner using map that gives you full control on the length and characters.
const rnd = (len, chars='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789') => [...Array(len)].map(() => chars.charAt(Math.floor(Math.random() * chars.length))).join('')
console.log(rnd(12))

Categories