Does parseInt return a strict integer? - javascript

My understanding was that javascript doesn't strictly speaking have an integer datatype, but I'm coming across a weird problem that's having me second guess myself.
I'm trying to build a simple custom rounding function using parseInt to drop extra decimal places, but the full function always returns an integer:
function round(num, places){
return (parseInt(num*10^places) + 0.5)/10^places
}
For completeness, I'm using this function within another:
function convertDegrees(val, uom){
if (uom === "celcius"){
return round(val * 9/5 + 32, 2) + " degrees Fahrenheit"}
else {
return round((val - 32) * 5/9, 2) + " degrees Celcius"}
}
But I don't see what in that would cause the problem either.

It looks like you want to raise something to an exponent which needs ** not ^ which is bitwise XOR
function round(num, places) {
return (parseInt(num * 10 ** places) + 0.5) / 10 ** places
}
function convertDegrees(val, uom) {
if (uom === "celcius") {
return round(val * 9 / 5 + 32, 2) + " degrees Fahrenheit"
} else {
return round((val - 32) * 5 / 9, 2) + " degrees Celcius"
}
}
console.log(convertDegrees(0, 'celcius'))

Related

round, decimal places, javascript [duplicate]

in JavaScript, the typical way to round a number to N decimal places is something like:
function roundNumber(num, dec) {
return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
}
function roundNumber(num, dec) {
return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
}
console.log(roundNumber(0.1 + 0.2, 2));
console.log(roundNumber(2.1234, 2));
However this approach will round to a maximum of N decimal places while I want to always round to N decimal places. For example "2.0" would be rounded to "2".
Any ideas?
I think that there is a more simple approach to all given here, and is the method Number.toFixed() already implemented in JavaScript.
simply write:
var myNumber = 2;
myNumber.toFixed(2); //returns "2.00"
myNumber.toFixed(1); //returns "2.0"
etc...
I found a way. This is Christoph's code with a fix:
function toFixed(value, precision) {
var precision = precision || 0,
power = Math.pow(10, precision),
absValue = Math.abs(Math.round(value * power)),
result = (value < 0 ? '-' : '') + String(Math.floor(absValue / power));
if (precision > 0) {
var fraction = String(absValue % power),
padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
result += '.' + padding + fraction;
}
return result;
}
Read the details of repeating a character using an array constructor here if you are curious as to why I added the "+ 1".
That's not a rounding ploblem, that is a display problem. A number doesn't contain information about significant digits; the value 2 is the same as 2.0000000000000. It's when you turn the rounded value into a string that you have make it display a certain number of digits.
You could just add zeroes after the number, something like:
var s = number.toString();
if (s.indexOf('.') == -1) s += '.';
while (s.length < s.indexOf('.') + 4) s += '0';
(Note that this assumes that the regional settings of the client uses period as decimal separator, the code needs some more work to function for other settings.)
There's always a better way for doing things. Use toPrecision -
var number = 51.93999999999761;
I would like to get four digits precision: 51.94
just do:
number.toPrecision(4);
the result will be: 51.94
This works for rounding to N digits (if you just want to truncate to N digits remove the Math.round call and use the Math.trunc one):
function roundN(value, digits) {
var tenToN = 10 ** digits;
return /*Math.trunc*/(Math.round(value * tenToN)) / tenToN;
}
Had to resort to such logic at Java in the past when I was authoring data manipulation E-Slate components. That is since I had found out that adding 0.1 many times to 0 you'd end up with some unexpectedly long decimal part (this is due to floating point arithmetics).
A user comment at Format number to always show 2 decimal places calls this technique scaling.
Some mention there are cases that don't round as expected and at http://www.jacklmoore.com/notes/rounding-in-javascript/ this is suggested instead:
function round(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}
PHP-Like rounding Method
The code below can be used to add your own version of Math.round to your own namespace which takes a precision parameter. Unlike Decimal rounding in the example above, this performs no conversion to and from strings, and the precision parameter works same way as PHP and Excel whereby a positive 1 would round to 1 decimal place and -1 would round to the tens.
var myNamespace = {};
myNamespace.round = function(number, precision) {
var factor = Math.pow(10, precision);
var tempNumber = number * factor;
var roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor;
};
myNamespace.round(1234.5678, 1); // 1234.6
myNamespace.round(1234.5678, -1); // 1230
from Mozilla Developer reference for Math.round()
Hopefully working code (didn't do much testing):
function toFixed(value, precision) {
var precision = precision || 0,
neg = value < 0,
power = Math.pow(10, precision),
value = Math.round(value * power),
integral = String((neg ? Math.ceil : Math.floor)(value / power)),
fraction = String((neg ? -value : value) % power),
padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
return precision ? integral + '.' + padding + fraction : integral;
}
I think below function can help
function roundOff(value,round) {
return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
}
usage : roundOff(600.23458,2); will return 600.23
function roundton(num, n) {
return Number(num.toFixed(n));
}
This uses JS's built-in method Number.prototype.toFixed which is meant for formatting strings but allows us to round to a specific number of digits. the Number() call converts it back to a number object cleanly
Ideally, we wouldn't need to convert it to a string, but toFixed is written in native C++ doing basic cstring operations so it's likely still fast.
If you do not really care about rounding, just added a toFixed(x) and then removing trailing 0es and the dot if necessary. It is not a fast solution.
function format(value, decimals) {
if (value) {
value = value.toFixed(decimals);
} else {
value = "0";
}
if (value.indexOf(".") < 0) { value += "."; }
var dotIdx = value.indexOf(".");
while (value.length - dotIdx <= decimals) { value += "0"; } // add 0's
return value;
}

Why is my rubik's cube calculation off by 4000?

I'm trying to throw together some quick and dirty javascript code to give me the number of possible piece permutations on a rubik's cube given a constraint such as "1 edgepiece is solved". (sticking to 3x3 for simplicity) When I run the normal 12 edgepieces and 8 corners through my function, it's giving me a number that is 4000 greater than what I'm able to find should be the answer. (Function gives me 43,252,003,274,489,860,000 but https://www.youtube.com/watch?v=z2-d0x_qxSM says it should be 43,252,003,274,489,856,000)
My code:
// 3x3x3 Rubik's Cube
edgepieces = 12;
cornerpieces = 8;
centerpieces = 6;
// total possible permutations in general
function numCombos(edges, corners) {
result = ((factorial(edges) * (factorial(corners)) / 2) * (2 ** (edges - 1)) * (3 ** (corners - 1)));
return result;
}
// n!
function factorial(x) {
if (x == 0) {
return 1;
} else {
return x * factorial(x - 1);
}
}
console.log(numCombos(edgepieces, cornerpieces) + '\n');
I have followed a couple different arrangements for the core result algorithm, and they all give me this end result. What am I missing?
You can use BigInt values to avoid floating-point precision issues:
// 3x3x3 Rubik's Cube
edgepieces = 12n;
cornerpieces = 8n;
centerpieces = 6n;
// total possible permutations in general
function numCombos(edges, corners) {
result = ((factorial(edges) * (factorial(corners)) / 2n) * (2n ** (edges - 1n)) * (3n ** (corners - 1n)));
return result;
}
// n!
function factorial(x) {
if (x == 0) {
return 1n;
} else {
return x * factorial(x - 1n);
}
}
console.log(numCombos(edgepieces, cornerpieces) + '\n');
Double-precision floating-point numbers have 53 bits of precision, which is almost 16 digits of precision.[1] You expect a result with 17 digits of precision. It's possible the number can't even be represented by a double.
The simple solution is to use BigInt numbers instead of floating point numbers.
log10( 253 ) = 15.95...

Eloquent JavaScript: Can't understand recursion example [duplicate]

This question already has answers here:
How does Eloquent JavaScript recursion example terminate as return 1 but still output exponential value
(2 answers)
Closed 7 years ago.
From page 50 of Haverbeke's second edition. I added a couple of console.log to try to better track the progress.
function power(base, exponent) {
if (exponent == 0) {
console.log("line 5 " + base + " " + exponent);
return 1;
}
else
console.log("line 10 " + base + " " + exponent);
return base * power(base, exponent -1);
}
console.log(power(2,3));
// Output
line 10 2 3
line 10 2 2
line 10 2 1
line 5 2 0
8
//
I expect the final output to be 1 since when the if (exponent == 0) is true, the next statement is return 1;, but it appears to enter the else one more time to return 8. But shouldn't the return kick us out of the function.
Obviously a newbie or wouldn't be stuck on page 50 of a supposedly beginner book.
Thanks for any help.
Whenever the function enters the "else" branch, a new stack frame is created, waiting for the result of the recursive call. You can imagine the evaluation step by step:
power(2, 3) enters the else branch, and it returns base * power(base, exponent - 1).
2 * power (2, 2) enters the else branch, and it returns base * power(base, exponent - 1).
2 * (2 * power (2, 1)) enters the else branch, and it returns base * power(base, exponent - 1).
2 * (2 * (2 * power (2, 0))) enters the if branch, and it returns 1.
You can finally evaluate the result: 2 * (2 * (2 * 1)), which is 8.
The end result of the function call power(2,3) is not the last return, but the combination of returned values, by the subsequent internal function calls. Let's deconstruct the recursive function:
power(2,3) returns 2 * power(2,2)
power(2,2) returns 2 * power(2,1)
power(2,1) returns 2 * power(2,0)
power(2,0) returns 1
So in total, power(2,3) returns 2 * 2 * 2 * 1 which is equal to 8.
The return statement exits from one invocation of the function. In order to get to the return 1; line, the function will have been called several times (based on the original value of the exponent).
The first invocation is
console.log(power(2,3));
Inside the function, subsequent invocations take place here:
return base * power(base, exponent -1);
Each one will correspond with a return.
Oh, and as #TJCrowder notes in a comment, that code is not correct: the else part should be wrapped in { }:
if (exponent == 0) {
console.log("line 5 " + base + " " + exponent);
return 1;
}
else {
console.log("line 10 " + base + " " + exponent);
return base * power(base, exponent -1);
}
I'm assuming that the missing { } wrapper was a transcription error.

JavaScript math, round to two decimal places [duplicate]

This question already has answers here:
How to round to at most 2 decimal places, if necessary
(91 answers)
Closed 5 years ago.
I have the following JavaScript syntax:
var discount = Math.round(100 - (price / listprice) * 100);
This rounds up to the whole number. How can I return the result with two decimal places?
NOTE - See Edit 4 if 3 digit precision is important
var discount = (price / listprice).toFixed(2);
toFixed will round up or down for you depending on the values beyond 2 decimals.
Example: http://jsfiddle.net/calder12/tv9HY/
Documentation: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed
Edit - As mentioned by others this converts the result to a string. To avoid this:
var discount = +((price / listprice).toFixed(2));
Edit 2- As also mentioned in the comments this function fails in some precision, in the case of 1.005 for example it will return 1.00 instead of 1.01. If accuracy to this degree is important I've found this answer: https://stackoverflow.com/a/32605063/1726511 Which seems to work well with all the tests I've tried.
There is one minor modification required though, the function in the answer linked above returns whole numbers when it rounds to one, so for example 99.004 will return 99 instead of 99.00 which isn't ideal for displaying prices.
Edit 3 - Seems having the toFixed on the actual return was STILL screwing up some numbers, this final edit appears to work. Geez so many reworks!
var discount = roundTo((price / listprice), 2);
function roundTo(n, digits) {
if (digits === undefined) {
digits = 0;
}
var multiplicator = Math.pow(10, digits);
n = parseFloat((n * multiplicator).toFixed(11));
var test =(Math.round(n) / multiplicator);
return +(test.toFixed(digits));
}
See Fiddle example here: https://jsfiddle.net/calder12/3Lbhfy5s/
Edit 4 - You guys are killing me. Edit 3 fails on negative numbers, without digging into why it's just easier to deal with turning a negative number positive before doing the rounding, then turning it back before returning the result.
function roundTo(n, digits) {
var negative = false;
if (digits === undefined) {
digits = 0;
}
if (n < 0) {
negative = true;
n = n * -1;
}
var multiplicator = Math.pow(10, digits);
n = parseFloat((n * multiplicator).toFixed(11));
n = (Math.round(n) / multiplicator).toFixed(digits);
if (negative) {
n = (n * -1).toFixed(digits);
}
return n;
}
Fiddle: https://jsfiddle.net/3Lbhfy5s/79/
If you use a unary plus to convert a string to a number as documented on MDN.
For example:+discount.toFixed(2)
The functions Math.round() and .toFixed() is meant to round to the nearest integer. You'll get incorrect results when dealing with decimals and using the "multiply and divide" method for Math.round() or parameter for .toFixed(). For example, if you try to round 1.005 using Math.round(1.005 * 100) / 100 then you'll get the result of 1, and 1.00 using .toFixed(2) instead of getting the correct answer of 1.01.
You can use following to solve this issue:
Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2');
Add .toFixed(2) to get the two decimal places you wanted.
Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2').toFixed(2);
You could make a function that will handle the rounding for you:
function round(value, decimals) {
return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
Example:
https://jsfiddle.net/k5tpq3pd/36/
Alternative
You can add a round function to Number using prototype. I would not suggest adding .toFixed() here as it would return a string instead of number.
Number.prototype.round = function(decimals) {
return Number((Math.round(this + "e" + decimals) + "e-" + decimals));
}
and use it like this:
var numberToRound = 100 - (price / listprice) * 100;
numberToRound.round(2);
numberToRound.round(2).toFixed(2); //Converts it to string with two decimals
Example
https://jsfiddle.net/k5tpq3pd/35/
Source: http://www.jacklmoore.com/notes/rounding-in-javascript/
To get the result with two decimals, you can do like this :
var discount = Math.round((100 - (price / listprice) * 100) * 100) / 100;
The value to be rounded is multiplied by 100 to keep the first two digits, then we divide by 100 to get the actual result.
The best and simple solution I found is
function round(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}
round(1.005, 2); // 1.01
try using discount.toFixed(2);
I think the best way I've seen it done is multiplying by 10 to the power of the number of digits, then doing a Math.round, then finally dividing by 10 to the power of digits. Here is a simple function I use in typescript:
function roundToXDigits(value: number, digits: number) {
value = value * Math.pow(10, digits);
value = Math.round(value);
value = value / Math.pow(10, digits);
return value;
}
Or plain javascript:
function roundToXDigits(value, digits) {
if(!digits){
digits = 2;
}
value = value * Math.pow(10, digits);
value = Math.round(value);
value = value / Math.pow(10, digits);
return value;
}
A small variation on the accepted answer.
toFixed(2) returns a string, and you will always get two decimal places. These might be zeros. If you would like to suppress final zero(s), simply do this:
var discount = + ((price / listprice).toFixed(2));
Edited:
I've just discovered what seems to be a bug in Firefox 35.0.1, which means that the above may give NaN with some values.
I've changed my code to
var discount = Math.round(price / listprice * 100) / 100;
This gives a number with up to two decimal places. If you wanted three, you would multiply and divide by 1000, and so on.
The OP wants two decimal places always, but if toFixed() is broken in Firefox it needs fixing first.
See https://bugzilla.mozilla.org/show_bug.cgi?id=1134388
Fastest Way - faster than toFixed():
TWO DECIMALS
x = .123456
result = Math.round(x * 100) / 100 // result .12
THREE DECIMALS
x = .123456
result = Math.round(x * 1000) / 1000 // result .123
function round(num,dec)
{
num = Math.round(num+'e'+dec)
return Number(num+'e-'+dec)
}
//Round to a decimal of your choosing:
round(1.3453,2)
Here is a working example
var value=200.2365455;
result=Math.round(value*100)/100 //result will be 200.24
To handle rounding to any number of decimal places, a function with 2 lines of code will suffice for most needs. Here's some sample code to play with.
var testNum = 134.9567654;
var decPl = 2;
var testRes = roundDec(testNum,decPl);
alert (testNum + ' rounded to ' + decPl + ' decimal places is ' + testRes);
function roundDec(nbr,dec_places){
var mult = Math.pow(10,dec_places);
return Math.round(nbr * mult) / mult;
}

Javascript: formatting a rounded number to N decimals

in JavaScript, the typical way to round a number to N decimal places is something like:
function roundNumber(num, dec) {
return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
}
function roundNumber(num, dec) {
return Math.round(num * Math.pow(10, dec)) / Math.pow(10, dec);
}
console.log(roundNumber(0.1 + 0.2, 2));
console.log(roundNumber(2.1234, 2));
However this approach will round to a maximum of N decimal places while I want to always round to N decimal places. For example "2.0" would be rounded to "2".
Any ideas?
I think that there is a more simple approach to all given here, and is the method Number.toFixed() already implemented in JavaScript.
simply write:
var myNumber = 2;
myNumber.toFixed(2); //returns "2.00"
myNumber.toFixed(1); //returns "2.0"
etc...
I found a way. This is Christoph's code with a fix:
function toFixed(value, precision) {
var precision = precision || 0,
power = Math.pow(10, precision),
absValue = Math.abs(Math.round(value * power)),
result = (value < 0 ? '-' : '') + String(Math.floor(absValue / power));
if (precision > 0) {
var fraction = String(absValue % power),
padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
result += '.' + padding + fraction;
}
return result;
}
Read the details of repeating a character using an array constructor here if you are curious as to why I added the "+ 1".
That's not a rounding ploblem, that is a display problem. A number doesn't contain information about significant digits; the value 2 is the same as 2.0000000000000. It's when you turn the rounded value into a string that you have make it display a certain number of digits.
You could just add zeroes after the number, something like:
var s = number.toString();
if (s.indexOf('.') == -1) s += '.';
while (s.length < s.indexOf('.') + 4) s += '0';
(Note that this assumes that the regional settings of the client uses period as decimal separator, the code needs some more work to function for other settings.)
There's always a better way for doing things. Use toPrecision -
var number = 51.93999999999761;
I would like to get four digits precision: 51.94
just do:
number.toPrecision(4);
the result will be: 51.94
This works for rounding to N digits (if you just want to truncate to N digits remove the Math.round call and use the Math.trunc one):
function roundN(value, digits) {
var tenToN = 10 ** digits;
return /*Math.trunc*/(Math.round(value * tenToN)) / tenToN;
}
Had to resort to such logic at Java in the past when I was authoring data manipulation E-Slate components. That is since I had found out that adding 0.1 many times to 0 you'd end up with some unexpectedly long decimal part (this is due to floating point arithmetics).
A user comment at Format number to always show 2 decimal places calls this technique scaling.
Some mention there are cases that don't round as expected and at http://www.jacklmoore.com/notes/rounding-in-javascript/ this is suggested instead:
function round(value, decimals) {
return Number(Math.round(value+'e'+decimals)+'e-'+decimals);
}
PHP-Like rounding Method
The code below can be used to add your own version of Math.round to your own namespace which takes a precision parameter. Unlike Decimal rounding in the example above, this performs no conversion to and from strings, and the precision parameter works same way as PHP and Excel whereby a positive 1 would round to 1 decimal place and -1 would round to the tens.
var myNamespace = {};
myNamespace.round = function(number, precision) {
var factor = Math.pow(10, precision);
var tempNumber = number * factor;
var roundedTempNumber = Math.round(tempNumber);
return roundedTempNumber / factor;
};
myNamespace.round(1234.5678, 1); // 1234.6
myNamespace.round(1234.5678, -1); // 1230
from Mozilla Developer reference for Math.round()
Hopefully working code (didn't do much testing):
function toFixed(value, precision) {
var precision = precision || 0,
neg = value < 0,
power = Math.pow(10, precision),
value = Math.round(value * power),
integral = String((neg ? Math.ceil : Math.floor)(value / power)),
fraction = String((neg ? -value : value) % power),
padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
return precision ? integral + '.' + padding + fraction : integral;
}
I think below function can help
function roundOff(value,round) {
return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
}
usage : roundOff(600.23458,2); will return 600.23
function roundton(num, n) {
return Number(num.toFixed(n));
}
This uses JS's built-in method Number.prototype.toFixed which is meant for formatting strings but allows us to round to a specific number of digits. the Number() call converts it back to a number object cleanly
Ideally, we wouldn't need to convert it to a string, but toFixed is written in native C++ doing basic cstring operations so it's likely still fast.
If you do not really care about rounding, just added a toFixed(x) and then removing trailing 0es and the dot if necessary. It is not a fast solution.
function format(value, decimals) {
if (value) {
value = value.toFixed(decimals);
} else {
value = "0";
}
if (value.indexOf(".") < 0) { value += "."; }
var dotIdx = value.indexOf(".");
while (value.length - dotIdx <= decimals) { value += "0"; } // add 0's
return value;
}

Categories