How to reverse numeric value having scientific notation in nodeJS? - javascript

I want to understand best way to reverse an integer (both positive and negative) in NodeJS 12. Can we do this without converting number to string? It should also support scientific notation numbers like 1e+10 which is 10000000000.
Input/Expected Output
500 = 5
-94 = -49
1234 = 4321
-1 = -1
1e+10 = 1
123.45e+10 = 54321

This is the answer I could come up with but I feel there might be better way. I didn't like the way I had to convert the integer to string, reverse it and again convert it back to integer.
parseInt(Math.sign(num) * parseInt(Math.abs(num).toString().split("").reverse().join("")))

function reverseNum(num) {
return (
parseFloat(
num
.toString()
.split('')
.reverse()
.join('')
) * Math.sign(num)
)
}

I hope this one line function solves your use-case
// The Math.sign() function returns either a positive or negative +/- 1,
// indicating the sign of a number passed into the argument.
function reverseInt(n) {
return parseInt(n.toString().split('').reverse().join('')) * Math.sign(n)
}
console.log(reverseInt(500));
console.log(reverseInt(-94));
console.log(reverseInt(1234));

Related

How to round down integer to all zeros behind first number

For example, I need to round number 6588 => 6000 , 1285000 => 1000000
I can't find any Math.ceil , Math.floor methods that can achieve this.
You can divide by the highest power of ten, floor it, then multiply back by the highest power of ten. Some other answers are manipulating string, but IMO this is the simplest and easiest to read code. Like this:
function roundDown(num) {
let powerOfTen = num.toString().length - 1;
num /= (10**powerOfTen);
return Math.floor(num) * (10**powerOfTen);
}
console.log(roundDown(6588)) // => 6000
console.log(roundDown(1285000)) // => 1000000
This is roughly the same procedure that Math.floor() uses, as described in this MDN article;
another variant is just work on string level, instead of numbers to avoid any floating point problems
function roundToFirst(n) {
return (''+n).split('').map((c, i) => i > 0 ? '0' : c).join('');
}
console.log(roundToFirst(6588)); // 6000
console.log(roundToFirst(1285000)); // 1000000
You can convert your number to a string and simply append zeros to match the number's length.
const roundDown = (num) => {
num = num.toString();
return (num[0] + new Array(num.length).join('0'));
}
console.log(roundDown(6588))
console.log(roundDown(0))
A short and easy way is to take the first digit and padEnd the rest
const roundDown = num => {
num = String(num)
return +num[0].padEnd(num.length, "0")
}
console.log(roundDown(6588))
console.log(roundDown(1285000))
References
padEnd

Truncate a number

function truncDigits(inputNumber, digits) {
const fact = 10 ** digits;
return Math.trunc(inputNumber * fact) / fact;
}
truncDigits(27624.399999999998,2) //27624.4 but I want 27624.39
I need to truncate a float value but don't wanna round it off. For example
27624.399999999998 // 27624.39 expected result
Also Math.trunc gives the integer part right but when you Math.trunc value 2762439.99 it does not give the integer part but gives the round off value i.e 2762434
Probably a naive way to do it:
function truncDigits(inputNumber, digits) {
return +inputNumber.toString().split('.').map((v,i) => i ? v.slice(0, digits) : v).join('.');
}
console.log(truncDigits(27624.399999999998,2))
At least it does what you asked though
Try this:
function truncDigits(inputNumber, digits){
return parseFloat((inputNumber).toFixed(digits));
}
truncDigits(27624.399999999998,2)
Your inputs are number (if you are using typescript). The method toFixed(n) truncates your number in a maximum of n digits after the decimal point and returns it as a string. Then you convert this with parseFloat and you have your number.
You can try to convert to a string and then use a RegExp to extract the required decimals
function truncDigits(inputNumber: number, digits: number) {
const match = inputNumber.toString().match(new RegExp(`^\\d+\\.[\\d]{0,${digits}}`))
if (!match) {
return inputNumber
}
return parseFloat(match[0])
}
Note: I'm using the string version of the RegExp ctor as the literal one doesn't allow for dynamic params.

Find out the maximum number of decimal places within a string of numbers

The string looks like this like something along the lines of 3*2.2or 6+3.1*3.21 or (1+2)*3,1+(1.22+3) or 0.1+1+2.2423+2.1 it can vary a bit. I have to find the amount of decimal places in the number inside the string with the most decimal places.
Im totally helpless on how to do it
You can use a regular expression to find all numbers that have decimal places and then use Array.prototype.reduce to find the highest amount of decimal places.
const input = '0.1+1+2.2423+2.1';
const maxNumberOfDecimalPlaces = input
.match(/((?<=\.)\d+)/g)
?.reduce((acc, el) =>
acc >= el.length ?
acc :
el.length, 0) ?? 0;
console.log(maxNumberOfDecimalPlaces);
Note that this will return 0 when no numbers with decimal places are found in the string.
You may do the following:
Array.prototype.split() your input string by RegExp /\[^\d.\]+/ to extract numbers
traverse resulting array of numbers with Array.prototype.map() and split those by decimal separator into whole and fractional parts, returning the length of the fractional part or 0 (for integers)
use Math.max() to find the maximum length
Above method seems to be more robust as it does not involve certain not well supported features:
RegExp lookbehinds assertions (/(?<=)/) which may not be supported by certain popular browsers like Safari or Firefox (below current version)
latest features, like conditional chaining (.?) or nulish coalescing (??)
const src = ['3*2.2', '6+3.1*3.21', '(1+2)*3' , '1+(1.22+3)', '0.1+1+2.2423+2.1'],
maxDecimals = s =>
Math.max(
...s
.split(/[^\d.]+/)
.map(n => {
const [whole, fract] = n.split('.')
return fract ? fract.length : 0
})
)
src.forEach(s => console.log(`Input: ${s}, result: ${maxDecimals(s)}`))
.as-console-wrapper{min-height:100%;}
You could use regex pattern
var str="6+3.1*3.21"
d=str.match(/(?<=\d)[.]\d{1,}/g)
d!=null ? res=d.map((n,i) => ({["number" + (i+1) ] : n.length - 1}))
: res = 0
console.log(res)

Javascript string/integer comparisons

I store some parameters client-side in HTML and then need to compare them as integers. Unfortunately I have come across a serious bug that I cannot explain. The bug seems to be that my JS reads parameters as strings rather than integers, causing my integer comparisons to fail.
I have generated a small example of the error, which I also can't explain. The following returns 'true' when run:
console.log("2" > "10")
Parse the string into an integer using parseInt:
javascript:alert(parseInt("2", 10)>parseInt("10", 10))
Checking that strings are integers is separate to comparing if one is greater or lesser than another. You should always compare number with number and string with string as the algorithm for dealing with mixed types not easy to remember.
'00100' < '1' // true
as they are both strings so only the first zero of '00100' is compared to '1' and because it's charCode is lower, it evaluates as lower.
However:
'00100' < 1 // false
as the RHS is a number, the LHS is converted to number before the comparision.
A simple integer check is:
function isInt(n) {
return /^[+-]?\d+$/.test(n);
}
It doesn't matter if n is a number or integer, it will be converted to a string before the test.
If you really care about performance, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
return function(n) {
return re.test(n);
}
}());
Noting that numbers like 1.0 will return false. If you want to count such numbers as integers too, then:
var isInt = (function() {
var re = /^[+-]?\d+$/;
var re2 = /\.0+$/;
return function(n) {
return re.test((''+ n).replace(re2,''));
}
}());
Once that test is passed, converting to number for comparison can use a number of methods. I don't like parseInt() because it will truncate floats to make them look like ints, so all the following will be "equal":
parseInt(2.9) == parseInt('002',10) == parseInt('2wewe')
and so on.
Once numbers are tested as integers, you can use the unary + operator to convert them to numbers in the comparision:
if (isInt(a) && isInt(b)) {
if (+a < +b) {
// a and b are integers and a is less than b
}
}
Other methods are:
Number(a); // liked by some because it's clear what is happening
a * 1 // Not really obvious but it works, I don't like it
Comparing Numbers to String Equivalents Without Using parseInt
console.log(Number('2') > Number('10'));
console.log( ('2'/1) > ('10'/1) );
var item = { id: 998 }, id = '998';
var isEqual = (item.id.toString() === id.toString());
isEqual;
use parseInt and compare like below:
javascript:alert(parseInt("2")>parseInt("10"))
Always remember when we compare two strings.
the comparison happens on chacracter basis.
so '2' > '12' is true because the comparison will happen as
'2' > '1' and in alphabetical way '2' is always greater than '1' as unicode.
SO it will comeout true.
I hope this helps.
You can use Number() function also since it converts the object argument to a number that represents the object's value.
Eg: javascript:alert( Number("2") > Number("10"))
+ operator will coerce the string to a number.
console.log( +"2" > +"10" )
The answer is simple. Just divide string by 1.
Examples:
"2" > "10" - true
but
"2"/1 > "10"/1 - false
Also you can check if string value really is number:
!isNaN("1"/1) - true (number)
!isNaN("1a"/1) - false (string)
!isNaN("01"/1) - true (number)
!isNaN(" 1"/1) - true (number)
!isNaN(" 1abc"/1) - false (string)
But
!isNaN(""/1) - true (but string)
Solution
number !== "" && !isNaN(number/1)
The alert() wants to display a string, so it will interpret "2">"10" as a string.
Use the following:
var greater = parseInt("2") > parseInt("10");
alert("Is greater than? " + greater);
var less = parseInt("2") < parseInt("10");
alert("Is less than? " + less);

Why does toPrecision return a String?

View this code:
function testprecision(){
var isNotNumber = parseFloat('1.3').toPrecision(6);
alert(typeof isNotNumber); //=> string
}
I would have expected a number. If 'isNotNumber' should be a real number, recasting is the solution:
alert(typeof parseFloat(isNotNumber)) //=> number
[Edit]
thanks for your answers. Precision is not so precise a term I conclude. It can represent the total number of digits of a number, or the number of fractional digits. Most people in the Netherlands (where I come from) think of precision in the 'number of fractional digits'-way. The javascript toPrecision method concerns the first representation, so this is confusing. Anyway, the method makes it possible to introduce 'false precision', am I right? For the second meaning we have toFixed, the same goes for that (returns string, possibility of false precision).
Anyway, having made reinventing the wheel my main hobby, I played around to construct a javascript float object, using the knowledge I gathered here. Maybe it's usefull for someone out there, or maybe one of you have better ideas?
function Float(f,nDec) {
var Base = this,val;
setPrecision( nDec || 2 );
set( f || 0, nDec || Base.precision );
Base.set = set;
Base.ndec = setPrecision;
/** public setprecision
* sets a value for the number of fractional
* digits (decimals) you would like getf to
* return. NB: can't be more than 20.
* Returns the Float object, so allows method
* chaining
* #param {Number} iPrecision
*/
function setPrecision(iPrecision) {
var ix = parseInt(iPrecision,10) || 2;
Base.precision = ix >= 21 ? 20 : ix;
return Base;
}
/** public set
* sets the 'internal' value of the object. Returns
* the Float object, so allows method chaining
* #param {Number} f
* #param {Number} ndec
*/
function set(f,ndec) {
val = parseFloat(f) || 0;
if (ndec) { setPrecision(ndec); }
Base.val = val;
return Base;
}
/** public get:
* return number value (as a float)
*/
Base.get = function(){
var ndec = Math.pow(10,Base.precision),
ival = parseInt(val*ndec,10)/ndec;
Base.val = ival;
return Base.val;
};
/** public getf
* returns formatted string with precision
* (see Base.setPrecision)
* if [hx] is supplied, it returns
* the float as hexadecimal, otherwise
* #param {Boolean} hx
*/
Base.getf = function(hx){
var v = Base.val.toFixed(Base.precision);
return hx ? v.toString(16) : v;
};
/** public add
* adds [f] to the current value (if [f] is a
* Float, otherwise returns current value)
* optionally sets a new number of decimals
* from parameter [ndec]
* #param {Number} f
* #param {Number} ndec
*/
Base.add = function(f,ndec){
if ( parseFloat(f) || val===0) {
set(Base.val+parseFloat(f));
if (ndec) { setPrecision(ndec);}
}
return Base.get();
};
/** toString
* returns the internal value of the Float object
* functions like a getter (supposedly)
*/
Base.toString = Base.get;
}
usage/example:
var xf = new Float(); //=> value now 0.0
xf.set(0.86/0.8765,17).add(3.459);
alert(xf+'|'+xf.getf()); //=> 4.440175128351398|4.44017512835139800
From the docs: "Returns a string representing the Number object to the specified precision."
toPrecision() seems intended for formatting output, in which case a string is the most reasonable outcome. It represents the final output in a form that will not be mangled by further manipulation.
If you are looking to do some truncation of precision for calculation reasons, I tend to multiply by 10^n where n is the digits I want to keep, take an integer from that and then divide again by the same. This isn't perfect though: in some situations you may invite an overflow. Frankly, I prefer to do more complex financial calculations on the server, where I have a currency, binary coded decimal or similar numeric types.
Assume you have a number like '1.6'. If you format it to have 6 zeroes to the right, you would get a '1.600000'. To the computer, it is still the same number as 1.6, but to you and your website, it is not the same if all your numbers are of different lenghts (which could hurt a parser, for instance).
So, as to avoid it, toPrecision returns a string, or else the interpreter would reformat the number to become '1.6' again.
The purpose of toPrecision is to truncate the significant decimal digits of a Number to a specified amount. But the datatype of the internal representations of Numbers is binary IEEE-754 double. Therefore it's impossible to store the precise return value in a Number most of the times. As a result of this impreciseness, the return value would have an infinite amount of decimal digits which would render toPrecision void.
So the only reasonable solution to this problem is to return decimal digits. And currently the only reasonable JS datatype for decimal digits is a String.
Here's an example to clarify the impreciseness of Numbers if used for decimal digits:
// the following looks like something with 2 decimal digits:
var number = 1.6;
// but in fact it's a number with an infinite amount of decimal digits.
// let's look at the first 30 of them:
alert(number.toPrecision(30));
// 1.60000000000000008881784197001
Because it is a formatting function.
You need a string for trailing zeros. Currency display is a good example.
The problem is the use of toPrecision. Try it without.
var isNotNumber = parseFloat('1.3');
alert(typeof isNotNumber); //=> number

Categories

Resources