IntoTheDeep
IntoTheDeep

Reputation: 4118

Optimize javascript number function

My target is to get floor of number with javascript. For example:

// 23 -> 20;
// 234 -> 230;
// 2345 -> 2300;
...

I am using next function:

var usersCount = 23;
var rounded;
if (usersCount < 100) {
    rounded = Math.floor(usersCount / 10) * 10;
} else if (usersCount < 1000) {
    rounded = Math.floor(usersCount / 100) * 100;
} else if (usersCount < 10000) {
    rounded = Math.floor(usersCount / 1000) * 1000;
} else if (usersCount < 100000) {
    rounded = Math.floor(usersCount / 10000) * 10000;
} else if (usersCount < 1000000) {
    rounded = Math.floor(usersCount / 100000) * 100000;
} else {
    rounded = usersCount;
}

I need to improve that function to be dynamic in order to avoid putting else ifs or any kind of switches. How can I do that? I there any better approach to achieve wanted result?

Upvotes: 0

Views: 137

Answers (4)

wdm81
wdm81

Reputation: 121

The following function reproduces the behaviour given in your examples:

function f(x) {
    var m, u;
    m = Math.floor(Math.log10(x));
    u = Math.pow(10, Math.max(1, m - 1));
    return u * Math.floor(x / u);
}

If you would be happy with rounding to 2 significant figures you could use

function f(x) {
    return Number.parseFloat(x.toPrecision(2));
}

Upvotes: 0

The fourth bird
The fourth bird

Reputation: 163237

You could use the length of the string to calculate the multiplier using Math.pow:

const usersCount = 23;    
const round = s => {
    let c = Math.pow(10, s.toString().length - 1);
    return Math.floor(s / c) * c;
};
console.log(round(usersCount)); // 20

const round = s => {
  let c = Math.pow(10, s.toString().length - 1);
  return Math.floor(s / c) * c;
};
[
  23,
  199,
  888,
  99999,
  100001
].forEach(x => {
  console.log(round(x));
});

Upvotes: 0

Ernesto Stifano
Ernesto Stifano

Reputation: 3130

The most compact and optimised way I can think of right now to re-write your code is as follows:

let usersCount = 23;
let rounded;
let x = 10 ** (usersCount.toString().length - 1);
rounded = Math.floor(usersCount / x) * x;

It should work recursively with no limitations as you requested.

Upvotes: 0

Anand Chowdhary
Anand Chowdhary

Reputation: 450

You can use a function like this:

const userCount = 234567;

const roundIt = n => {
	const numberLength = Math.ceil(Math.log10(n + 1));
  const decrease = n > 100 ? 2 : 1;
  return Math.floor(n / Math.pow(10, numberLength - decrease)) * Math.pow(10, numberLength - decrease);
};

// Display user count
document.querySelector(".user-count").innerHTML = userCount;

// Display rounded count
document.querySelector(".user-count-rounded").innerHTML = roundIt(userCount);
<h1>
User count: <span class="user-count">0</span>
</h1>
<h1>
Rounded user count: <span class="user-count-rounded">0</span>
</h1>

We use the length of the number and round it using the same code you've written.

Here is a fiddle: https://jsfiddle.net/anandchowdhary/fj0zk1x8/7/

Upvotes: 1

Related Questions