Fastest way to cast a float to an int in javascript? - javascript

Let's say I have x = 12.345. In javascript, what function floatToInt(x) has the fastest running time such that floatToInt(12.345) returns 12?

Great Question! I actually had to deal with this the other day! It may seem like a goto to just write parseInt but wait! we can be fancier.
So we can use bit operators for quite a few things and this seems like a great situation! Let's say I have the number from your question, 12.345, I can use the bit operator '~' which inverts all the bits in your number and in the process converts the number to an int! Gotta love JS.
So now we have the inverted bit representation of our number then if we '~' it again we get ........drum roll......... our number without the decimals! Unfortunately, it doesn't do rounding.
var a = 12.345;
var b = ~~a; //boom!
We can use Math.round() for that. But there you go! You can try it on JSperf to see the slight speed up you get! Hope that helps!

this is a good example i think
var intvalue = Math.floor( floatvalue );
var intvalue = Math.ceil( floatvalue );
var intvalue = Math.round( floatvalue );

just do:
~~(x + 0.5)
Cheers, Z.

Arithmetic OR with zero does the trick.
> 12 === (0 | 12.245)
true

parseInt(x) does the work.
If you were running checks to see if the returned value is actually an int without the knowledge of what is the input.
x = 12.245; // Issa number
x = 'School'; // Not a number
y = parseInt(x)
if isNaN(y)
console.log('Not a number');
else
console.log('Issa number');
// Issa number
while using y = ~~x is a totally different case
x = 12.245; // Issa number
x = 'School'; // Issa number
y = ~~x;
if isNaN(y)
console.log('Not a number');
else
console.log('Issa number');

If you don't care about the rounding specifics, Math.trunc() is easy, standard, and readable. I haven't tested performance, but it must be better than Math.round() and parseInt().

In my own testing, I've found that the rule of thumb for performance is:
Bitwise operations (~~num, num|0, num^0, num&0xFFFFFFFF)
Math methods
num - (num % 1)
parseInt
The issue with bitwise operators is that the numbers will be cast to 32bit integers in the process, if that is fine for your use-case then go ahead. See MDN docs on bitwise OR, bitwise NOT, bitwise AND and bitwise XOR or their respective ECMAScript documentation.
The parseInt function is usually way slower than the alternatives, most likely because it expects a string as parameter.
The solution with the modulo operator should be used with caution as it may bite you in the ass sometime due to floating point issues but is almost as fast as the Math methods.

Related

Project Euler #16 not working?

I was certain i had my code right, however it returns 1364 rather than the correct answer 1366.
I tested my code for 2^15 and it returned the correct answer 26. I also tried a few other numbers, all of which gave me a correct answer.
I know my code is very elementary, i don't know much Javascript and i am open to alternate solutions, however i am looking for an explanation as to why my code does not work.
//adds digits of this number
sum(Math.pow(2,1000));
function sum(x) {
//the upper limit of the number
var c = Math.floor(Math.log10(x));
//the sum
var s = 0;
//the ith digit
var a;
for (var i = c; i >= 0; i--) {
//this works, test by removing the slashes before console.log(a)
a = Math.floor((x % Math.pow(10,i+1)) / Math.pow(10,i));
s += a;
//console.log(a);
}
console.log(s);
}
Expanding on guest271314's comment:
Javascript numbers have IEEE 754 double-precision floating point behavior. This means that Javascript is unable to accurately represent integers above 253.
> Number.isSafeInteger(Math.pow(2, 15))
< true
> Number.isSafeInteger(Math.pow(2, 1000))
< false
To solve this problem in Javascript, you will need a different representation of 21000. Since the only operations you care about are exponentiation and reading out digits base 10, one possible representation is a decimal string, implementing multiplication yourself.

How to write Mathematical formula with "^" (caret) in JavaScript?

I need some help how to make this math formula in javascript. i have tried searching but couldn't really find cause i dont even know what ^ is called in English.
Thanks in advance
Math.floor(20*(1.1^(x-10)));
Math.floor(20*(Math.pow(1.1, (x-10))));
^ is the bitwise XOR operator - not what you want. Use the Math.pow function for exponentiation:
Math.floor( 20 * (Math.pow(1.1, x - 10)) );
Set this up in a function so you can use x for whatever value it may be:
var eq = function(x) {
return Math.floor( 20 * (Math.pow(1.1, x - 10)) );
};
Math.pow() is what you are looking for.
^, as used in other languages, is called the power or exponential operator, but in Javascript, it serves a different purpose, it is the bitwise XOR operator.
Math.floor(20*(Math.pow(1.1, x - 10)));

strip decimal points from variable

I have a series of variables that have a decimal point and a few zeros. How do I strip the variable so it goes from 1.000 to 1?
Simply...
Math.round(quantity);
...assuming you want to round 1.7 to 2. If not, use Math.floor for 1.7 to 1.
use parseInt();
parseInt("1.25");//returns 1
parseInt("1.85");//returns 1
parseInt(1.25);//returns 1
parseInt(1.85);//returns 1
Use number = ~~number
This is the fastest substitute to Math.floor()
parseInt is the slowest method
math.floor is the 2nd slowest method
faster methods not listed here are:
var myInt = 1.85 | 0;
myInt = 1;
var myInt = 1.85 >> 0;
myInt = 1;
Speed tests done here:
http://jsperf.com/math-floor-vs-math-round-vs-parseint/2
Use Math.trunc(). It does exactly what you ask. It strips the decimal.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/trunc
For rounding numbers to the nearest Integer you can use Math.round() like so:
Math.round("1.000"); // Will produce 1
Math.round(123.4234); // Will produce 123
You don't need jQuery for this.
You can use parseInt just fine. From the page:
document.write(parseInt("10.33") + "<br />"); // 10
Here's another nice example:
I often use Math.round and toLocateString to convert numbers containing decimal places, into a more readable string, with thousand separators:
var myNumberAsString = "1234567.890123" // "1234567.890123"
var myNumber = Math.round(0.0 + myNumberAsString); // 1234568
return myNumber.toLocaleString(); // "1,234,568"
I find this useful when loading decimal values from, say a JSON Web Service, and need to display them in a friendlier format on a web page (when, of course, I don't need to display all of the decimal places).
A faster, more efficient way would be to use JavaScript's bitwise operators, like so:
function stripDecimals(n) {
return n | 0;
}
// examples:
stripDecimals(23.245); // => 23
stripDecimals(100.015020); // => 100
The | (OR operator) will treat the numbers as 32-bit (binary 0s and 1s), followed by returning the desired result depending on the operands, which in this case would result to an integer stripped of all decimal places.
I suggest you use something called Math.trunc()... put your number in the parentheses. The reason I don't suggest you use Math.round() is that it might change the integer part of your decimal number which some people won't want though you can use Math.round() if you know you want to get the closest integer.

Currency Math in JavaScript

Can someone please help me out with a JavaScript/jQuery solution for this arithmetic problem:
I need to subtract one number from the other.
The problem is that the numbers have a dollar sign (because its money), therefore jQuery is treating them as strings instead of numbers.
I have created two variables - toalAssets and totalLiabilites. I would like to subtract the latter from the former and place the result into another variable called netWorth.
Perhaps i need to use parseFloat()?
But I'm not sure how - This is all a little over my head!
var totalLiabilites = '$52.34';
var toalAssets = '$85.12';
var pattern = /[^0-9.-]+/g;
var result = parseFloat(toalAssets.replace(pattern, '')) -
parseFloat(totalLiabilites.replace(pattern, ''));
// result: 32.78
Note: In JavaScript it is recommended1 to handle money as an integer representing the number of cents (8512 instead of 85.12). This is to avoid problems with floating-point arithmetic. 0.1 + 0.2 == 0.3 returns false in JavaScript, but fortunately integer arithmetic in floating point is exact, so decimal representation errors can be avoided by scaling.
You may want to check the following post for further reading on this topic: Is JavaScript’s math broken?
You can always apply the currency-sign formatting when the values are rendered to the browser.
1Douglas Crockford: JavaScript: The Good Parts: Appendix A - Awful Parts (page 105).
parseFloat() won't work because your string begins with a non-number, the dollar sign.
You can simply do a replace to remove the dollar sign, along with a parseFloat to get the value:
totalAssets = parseFloat(totalAssets.replace('$', ''));
totalLiabilities = parseFloat(totalLiabilities.replace('$', ''));
var difference = '$' + (totalAssets - totalLiabilities);
This code replaces your original strings with floats. You could load them into new variables as well. Likewise, difference does not have to have the '$' prepended.
var a = "$20";
var b = "$34";
var c = parseFloat(a.replace(/[^0-9\.]+/g, "")) - parseFloat(b.replace(/[^0-9\.]+/g, ""));
alert(c);

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