What does Math.random() do in this JavaScript snippet? - javascript

I'm watching this Google I/O presentation from 2011 https://www.youtube.com/watch?v=M3uWx-fhjUc
At minute 39:31, Michael shows the output of the closure compiler, which looks like the code included below.
My question is what exactly is this code doing (how and why)
// Question #1 - floor & random? 2147483648?
Math.floor(Math.random() * 2147483648).toString(36);
var b = /&/g,
c = /</g,d=/>/g,
e = /\"/g,
f = /[&<>\"]/;
// Question #2 - sanitizing input, I get it...
// but f.test(a) && ([replaces]) ?
function g(a) {
a = String(a);
f.test(a) && (
a.indexOf("&") != -1 && (a = a.replace(b, "&")),
a.indexOf("<") != -1 && (a = a.replace(c, "<")),
a.indexOf(">") != -1 && (a = a.replace(d, ">")),
a.indexOf('"') != -1 && (a = a.replace(e, """))
);
return a;
};
// Question #3 - void 0 ???
var h = document.getElementById("submit-button"),
i,
j = {
label: void 0,
a: void 0
};
i = '<button title="' + g(j.a) + '"><span>' + g(j.label) + "</span></button>";
h.innerHTML = i;
Edit
Thanks for the insightful answers. I'm still really curious about the reason why the compiler threw in that random string generation at the top of the script. Surely there must be a good reason for it. Anyone???

1) This code is pulled from Closure Library. This code in is simply creating random string. In later version it has been replaced by to simply create a large random integer that is then concatenated to a string:
'closure_uid_' + ((Math.random() * 1e9) >>> 0)
This simplified version is easier for the Closure Compiler to remove so you won't see it leftover like it was previously. Specifically, the Compiler assumes "toString" with no arguments does not cause visible state changes. It doesn't make the same assumption about toString calls with parameters, however. You can read more about the compiler assumptions here:
https://code.google.com/p/closure-compiler/wiki/CompilerAssumptions
2) At some point, someone determined it was faster to test for the characters that might need to be replaced before making the "replace" calls on the assumption most strings don't need to be escaped.
3) As others have stated the void operator always returns undefined, and "void 0" is simply a reasonable way to write "undefined". It is pretty useless in normal usage.

1) I have no idea what the point of number 1 is.
2) Looks to make sure that any symbols are properly converted into their corresponding HTML entities , so yes basically sanitizing the input to make sure it is HTML safe
3) void 0 is essentially a REALLY safe way to make sure it returns undefined . Since the actual undefined keyword in javascript is mutable (i.e. can be set to something else), it's not always safe to assume undefined is actually equal to an undefined value you expect.

When in doubt, check other bases.
2147483648 (base 10) = 0x80000000 (base 16). So it's just making a random number which is within the range of a 32-bit signed int. floor is converting it to an actual int, then toString(36) is converting it to a 36-character alphabet, which is 0-9 (10 characters) plus a-z (26 characters).
The end-result of that first line is a string of random numbers and letters. There will be 6 of them (36^6 = 2176782336), but the first one won't be quite as random as the others (won't be late in the alphabet). Edit: Adrian has worked this out properly in his answer; the first letter can be any of the 36 characters, but is slightly less likely to be Z. The other letters have a small bias towards lower values.
For question 2, if you mean this a = String(a); then yes, it is ensuring that a is a string. This is also a hint to the compiler so that it can make better optimisations if it's able to convert it to machine code (I don't know if they can for strings though).
Edit: OK you clarified the question. f.test(a) && (...) is a common trick which uses short-circuit evaluation. It's effectively saying if(f.test(a)){...}. Don't use it like that in real code because it makes it less readable (although in some cases it is more readable). If you're wondering about test, it's to do with regular expressions.
For question 3, it's new to me too! But see here: What does `void 0` mean? (quick google search. Turns out it's interesting, but weird)

There's a number of different questions rolled into one, but considering the question title I'll just focus on the first here:
Math.floor(Math.random() * 2147483648).toString(36);
In actual fact, this doesn't do anything - as the value is discarded rather than assigned. However, the idea of this is to generate a number between 0 and 2 ^ 31 - 1 and return it in base 36.
Math.random() returns a number from 0 (inclusive) to 1 (exclusive). It is then multipled by 2^31 to produce the range mentioned. The .toString(36) then converts it to base 36, represented by 0 to 9 followed by A to Z.
The end result ranges from 0 to (I believe) ZIK0ZI.
As to why it's there in the first place ... well, examine the slide. This line appears right at the top. Although this is pure conjecture, I actually suspect that the code was cropped down to what's visible, and there was something immediately above it that this was assigned to.

Related

Write a function that returns the square of a number without using *,+ or pow

The task is to write a function that takes n as an input where n is a number (from -32768 to 32768) and returns the square of that number. Simple task except for the fact that we cannot use any operators such as *,+ or even use any Math. functions such as pow. eval is not allowed as well.
Even more challenging is that we must keep the character code count less than 39 characters.
I absolutely cannot think of a way to get the square of a number without using the + or *. And even worse, to keep the character count less, it's impossible for me.
Codes like this won't work because: I used the plus sign and the character count is more than 60.
function sq(n){
var res=n;
for(i=1;i<n;i++)
res+=n;
return res;
}
If n is a decimal, we are expected to return the nearest whole number as the result.
Thank you for reading all of this!
Edit: My problem has been solved. Thank you to everyone who has tried to help me with their codes as it helped me gain a new aspect of solving each problems.
Thank you very much again!
You can try this as well
function multiply(a) {
return a / (1 / a);
}
console.log(multiply(6))
console.log(multiply(4))
The repeat() method returns a new string with a specified number of copies of the string it was called on. See here
This approach is limited to positive and integer numbers only.
// Another method
function multiplytwo(a) {
return ("i").repeat(a).repeat(a).length
}
console.log(multiplytwo(4))
console.log(multiplytwo(25))
//creating a string “i” and repeating it “a” times, then repeats that “a” times, and then returning the length.
You could divide n by 1 / n
For rounding off without using Math.round, I have used this:
s=n=>(r=>(r-~~r<.5?0:1)- -~~r)(n/(1/n))
console.log(s(5));
console.log(s(4.4));
console.log(s(-4.44));
This has 39 characters.
** is not in your list, so you might be able to use it:
sq = n => n ** 2
console.log(sq(5));
You could also use - twice, instead of +:
sq=n=>{s=0;for(let i=n;i>0;i--)s=s-(-n);return s}
console.log(sq(5));
(function definition is 49 characters)
If anyone still needs a solution that passes tests.
#adiga's solution works nicely. But if you need to be under 39 characters you can exploit JS implicit type coercion: substitute r-~~r<.5?0:1 by r-~~r<.5. It will give you a boolean which will be coerced to either 1 or 0. So, final solution is following:
s=n=>(r=>(r-~~r<.5)- -~~r)(n/(1/n))
As this just got brought back up, here is a 22-character solution:
sq=n=>~~-(-.5-n/(1/n))
;[[0, 0], [1, 1], [2, 4], [3, 9], [4.4, 19], [-4.44, 20], [32768, 1073741824]]
.forEach (([n, s]) => console .log (`sq(${n}) == ${s} //=> ${sq(n) == s}`))
Explanation
Like other answers here it takes advantage of the fact that n / (1/n) is mathematically equivalent to squaring n. This is also helped by the fact that although 1 / 0 is Infinity, 0 / Infinity gives back 0. Mathematically this is iffy, but for the problem it's perfect. The trick is then to round this to the nearest integer. We could do so like this:
let sq = (n) => Math .round(n / (1 /n) + 0.5)
But we have two issues here. First we take the fact that Math.round is disallowed by the rules. Here we can use a common substitution for Math.round, namely ~~. This is simply two consecutive applications of the bitwise NOT operator, which first removes any fractional part to convert the result to a 32-bit integer, then inverts all the bits. Doing it a second time acts much like integer truncation, giving something more like:
let sq = (n) => ~~ (n / (1 /n) + 0.5)
But we still have a + in the definition, also disallowed. But that can be replaced by subtracting the negation of the value, with a version like this:
let sq = (n) => ~~ (n / (1 /n) - -0.5)
Now, minifying this would give us
sq=(n)=>~~(n/(1/n)- -.5)
and this is an equivalent 22-character solution. But for some reason I really didn't like the space in that version, and since (a - b) is equivalent to - (b - a), we can create this alternative:
let sq=n=>~~-(-.5-n/(1/n))
I'm not generally much of a code-golfer. I simply don't see the point. But this was a fun little challenge.

Understanding Code To Determine If Number Is Odd Using ~~

I'm both a JavaScript / Node n0ob....but I was recently working on a project using both. I was exploring the /node_modules/ folder and I came across a particular line of code that didn't seem to immediately make sense to me. The goal is to determine if a number is odd or not.
The specific line of code is:
return !!(~~i & 1);
My question is 'Why do we need the ~~'
(related to: How to determine if a number is odd in JavaScript which shows most of the answers using % 2)
I think I understand the individual pieces.
!! is the negation operator (twice) and will give us a true/false value from a truthy/falsey value
~~ is a way to truncate a value. 8.234 becomes 8.
& is the bitwise and operator.
But I'm still questioning if we need the ~~, and if so, why?
I've been using N..toString(2) - for example:
4.0.toString(2)
> "100"
4.1.toString(2)
> "100.0001100110011001100110011001100110011001100110011"
To try and understand what the binary representations look like. In the second example, the right-most digit is a 1, but when I plug 4.1 in as the value for i, it still correctly sees that the number is even:
!!(~~4.1 & 1)
> false
!!(4.1 & 1)
> false
I've read that Javascript uses the IEEE 754 standard, and I've also read that all of the bitwise operators being used here do some implicit converting that I don't fully understand and maybe there are considerations that I'm not seeing?
Thanks
The double ~~ is used to convert a string to an number, just like !! is used to convert a truthy/falsey value to a boolean.
var a = "4";
console.log(typeof a + " " + a); //string
console.log(typeof ~a + " " + a); //converts to number, but you get (a - 1)
console.log(typeof ~~a + " " + a); // reverses the previous operation, keeping the number type
Now, as you realized, it's not necessary in this operations because in Javascript, when you do bitwise operations on strings they're first converted to numbers, so the double tilde becomes superfluous.
What I suspect was the intention of the maker of that snippet is that you can't really classify a decimal number as odd or even, so he just cast it as a number to get rid of the decimals, which ~~ does.

Using bitwise operators in javascript

I am creating a bitmask in javascript. It works fine for bit 0 through 14. When I set only bit fifteen to 1. It yields the integer value of "-2147483648" instead of "2147483648". I can do a special case hack here by returning hardcoded "2147483648" for bit fifteen but I would like to know the correct way of doing it.
Sample code:
function join_bitmap(hex_lower_word, hex_upper_word)
{
var lower_word = parseInt(hex_lower_word, 16);
var upper_word = parseInt(hex_upper_word, 16);
return (0x00000000ffffffff & ((upper_word<<16) | lower_word));
}
Above code returns -2147483648 when hex_lower_word is "0x0" and hex_upper_word is "0x8000" instead of 2147483648
The reason for this is because Javascript's bit shift operations use signed 32-bit integers. So if you do this:
0x1 << 31 // sets the 15th bit of the high word
It will set the sign bit to 1, which means negative.
On the other hand instead of bit shifting you multiply by powers of two, you'll get the result you want:
1 * Math.pow(2, 31)
The reason is, you are setting the sign bit...
2147483648 is 1 followed by 31 zeros in binary...
As you are doing a bitwise operation, the output is always a signed 32 bit number, which makes the 32nd bit the sign bit, so you get a negative number...
Update
(upper_word * Math.pow(2, 16))
will give positive 2147483648.
But, you still have the OR operation, which puts us back to square one...
As previous answers explained, the bitwise operators are 32 bit signed. Thus, if at any point along the way you set bit 31, things will go badly wrong.
In your code, the expression
(upper_word<<16) | lower_word)
is evaluated first because of the parentheses, and since upper_word has the top bit set, you will now have a negative number (0x80000000 = -2147483648)
The solution is to make sure that you do not shift a 1into bit 31 - so you have to set bit 15 of the upper word to zero before shifting:
mask15 = 0x7fff;
((upper_word&mask15)<<16|lower_word)
This will take care of "numbers that are too big become negative", but it won't solve the problem completely - it will just give the wrong answer! To get back to the right answer, you need to set bit 31 in the answer, iff bit 15 was set in upper_word:
bit15 = 0x8000;
bit31 = 0x80000000;
answer = answer + (upper_word & bit15)?bit31:0;
The rewritten function then becomes:
function join_bitmap(hex_lower_word, hex_upper_word)
{
var lower_word = parseInt(hex_lower_word, 16);
var upper_word = parseInt(hex_upper_word, 16);
var mask15 = 0x7fff;
var bit15 = 0x8000;
var bit31 = 0x80000000;
return 0xffffffff & (((upper_word&mask15)<<16) | lower_word) + ((upper_word & bit15)?bit31:0);
}
There isn't just a single "hard coded special case" - there are 2 billion or so. This takes care of all of them.

Is there a limit to the base to which numbers can be associated to?

This may be very convoluted and twisted idea. Got it while learning some JavaScript. It piqued my mind. Hoping there may be someone else who would have thought about it before or might enlighten me :-)
var n = 17;
binary_string = n.toString(2); // Evaluates to "10001"
octal_string = "0" + n.toString(8); // Evaluates to "021"
hex_string = "0x" + n.toString(16); // Evaluates to "0x11"
This made me probe more into bases. I remembered my Digital Engineering course and understood that for every number from 10 for a base greater than 10 will be started naming from 'a', 'b' onwards.
for eg:
var n = 10;
var y = 11;
string = n.toString(12); // Evaluates to 'a'
string = y.toString(12); // Evaluates to 'b'
Then I understood this could go uptil 'z'
Thus
var n = 35;
string = n.toString(36); // Evaluates to "z"
But that seems to be the end. if we do
var n = 35;
string = n.toString(37); // Gives error Error: illegal radix 37 { message="illegal radix 37", more...}
Thus I believe we can only count up to the bases of 36. since for a base 37 counting system, we wont be able to count 36 since we exhausted English characters. Is there anyway we can do it? Maybe we can add other characters.
I know it is very useless thing, and never in life will we ever need it.
But have anyone thought about it already?
see my question here. What symbols are used after base 36
Yes, of course it can be done, just not with JavaScript's toString function.
You just need to decide on which characters to use for your digits. This is largely arbitrary, although there are some established standards. See, for example, Base64, Ascii85 etc.
You can certainly do it, number bases are complete arbitrary (using the English alphabet after 9 is just a common convention). Number#toString is specifically designed to handle base 2 through 36:
The optional radix should be an integer value in the inclusive range 2 to 36.
From the spec, section 15.7.4.2.

parseInt alternative

Firstly - my description ;)
I've got a XmlHttpRequests JSON response from the server.
MySQL driver outputs all data as string and PHP returns it as it is, so any integer is returned as string, therefore:
Is there any fast alternative (hack) for parseInt() function in JS which can parse pure numeric string, e.g.
var foo = {"bar": "123"};
...
foo.bar = parseInt(foo.bar); // (int) 123
To convert to an integer simply use the unary + operator, it should be the fastest way:
var int = +string;
Conversions to other types can be done in a similar manner:
var string = otherType + "";
var bool = !!anything;
More info.
Type casting in JavaScript is done via the constructor functions of the built-in types without new, ie
foo.bar = Number(foo.bar);
This differs from parseInt() in several ways:
leading zeros won't trigger octal mode
floating point values will be parsed as well
the whole string is parsed, i.e. if it contains additional non-numeric characters, the return value will be NaN
First off, have you actually documented that it's slow and is causing problems? Otherwise, I wouldn't bother looking for a solution, because there really isn't a problem.
Secondly, I would guess that since parseInt is a native JS-method, it would be implemented in a way that is very fast, and probably in the native language of the VM (probably C, depending on the browser/VM). I think you could have some trouble making a faster method out of pure JS. =)
Of course, I'm not a JS guru, so I don't know for sure, but this is what my intuition tells me, and tends to be the standard answer to "how would I make a faster alternative for libraryFunction()?" questions.
Cast it to an int in PHP before you json_encode() it:
$foo->bar = (int)$foo->bar;
print('var foo = ' . json_encode($foo));
Incidentally, when using parseInt it's good practice to always specify the second parameter unless you really want string starting with 0 to be interpreted as octal and so on:
parseInt('010', 10); // 10
Fast shortcut to parseInt is
("78.5" | 0) //bitwise or forces the string to parse as int
This is what ASM uses to represent ints in js.
You aren't going to get better than parseInt, but the real bug is that the PHP is providing what is supposed to be a number as a string.
And ditto to what Daniel said - don't go looking for micro-optimisations like this until you have benchmarked your code and discovered that it's worth doing.
The Number constructor also exists, but it should be the same as parseInt in term of speed (as already said you should correct the PHP part instead of the javascript one anyway) :
var i = "123";
i = new Number(i); // Number numeric wrapper
var j = "123";
j = Number(j); // Number primitive
BTW if someone is interested i searched by curiosity for the V8 (Google chrome) implementation of parseInt and it's here on google code.
How slow can it be? How many times per second is this process being called? How many different numeric return values are there? I whipped together a script and tested 100,000 numbers. Parsing them from strings took 687ms. Searching them in an array took 541ms. That's a very small improvement. I agree with other posters. You may not get better than the native parseInt() method.
Casting is a wee bit faster than parsing but slower than searching.
Also, in Firefox the fastest method turns out to be parseInt() followed by searching. Firefox also turned out to be 6 times faster on average than IE. Interesting.
Cool idea using the unary operator. In Firefox that turned out to be comparable to parseInt(). In IE it turned out to be the fastest method.
if the objects are larger you could try JSON, it is a typed format so you do not need to convert the values.
This solution is faster than parseInt() if you parse strings of decimal integer that is 20 or less in length. For some browser, you may still be faster than parseInt() up to 33 digits in length. Also, you still be faster than auto-cast.
It is because, the parseInt() for the browser does take some time to warm up, so if you only using a simple method to parse, you beat it for a while until it catches up. Don't use this for nodeJS though. When run parseInt() from nodeJS, it is startup time is a lot less than when running from a browser.
45 is the '-' sign in ASCII, 43 is the '+' sign in ASCII. 48 is '0'. Only 48 to 57 xor 48 become 0 - 9(in their order). No other numbers xor 48 yields 0-9.
This will return undefined if the string is not a valid decimal integer string or if the string is empty. It throws a string with value "Not a string" if the input is not of type string.
var toNumber = function (input) {
if ( typeof input !== "string" ) throw "Not a string";
var length = input.length;
if ( length === 0 ) return;
var c1 = input.charCodeAt(0);
if ( c1 === 45 || c1 === 43 ){
if ( length === 1 ) return;
var start = 1;
} else {
var start = 0;
}
var out = 0, c;
while( start < length && input.charCodeAt(start) === 48 ) start++;
for ( ; start < length; start++){
c = input.charCodeAt(start) ^ 48;
if ( c > 9 ) return;
out = (out * 10) + c;
}
if ( c1 === 45 ) return out * -1;
return out;
}

Categories