Sum every element in a range in Javascript - javascript

I'm trying to make my small function work which adds every number together in a range.
For example when I call the method like: sumAll(3,10) it should do
3+4+5+6+7+8+9+10
It works if I give the function positive integers but if it receives a negative number or a string or an array for example, it doesn't work properly.. I just want to return "ERROR" if the supplied parameter is not a positive integer.
Can I have some help with this please? Is there a more elegant (better) way?
My code:
const sumAll = (...args) => {
let max = Math.max(...args);
let min = Math.min(...args);
if ((min < 0) || (!Number.isInteger(min)) || (!Number.isInteger(max)) || (Array.isArray(...args))) {
return "ERROR";
}
let n = (max - min) + 1;
return ((max + min) * n) / 2;
}

You could use a gaussian formular for getting a count from 1 ... n and subtract the sub count.
For getting only a result if possible, you could add a check for positive integers.
const
isPositiveInt = v => Number.isInteger(v) && v > 0,
sumN = n => n * (n + 1) / 2,
range = (m, n) => isPositiveInt(m) && isPositiveInt(n)
? sumN(Math.max(m, n)) - sumN(Math.min(m, n) - 1)
: 'ERROR';
console.log(range(3, 10));
console.log(range(10, 3));
console.log(range());
console.log(range(3));
console.log(range('', 10));
console.log(range(0.2, 0.3));

Related

How to Get the Middle Character from a string?

I am training on kata from CodeWars that can be found here https://www.codewars.com/kata/56747fd5cb988479af000028/train/javascript
I could not understand other solutions. My try is it:
const getMiddle = (s) => {
let middle = ""
for(let i = 0; i < s.length; i++) {
if(s.length % 2 === 1) {middle = s[s.length-1/2]}
if(s.length % 2 === 0) {middle = s[s.length-1/2-1] + s[s.length-1/2]}
} return middle
}
You're making this far more complicated than it needs to be.
You don't need a loop, since the length is not dependent on i.
Instead of checking whether the length is odd or even, you can just divide by 2 and round down.
function getMiddle(s) {
return Math.floor(s.length / 2);
}
s.length / 2 will return number in floating point if the s length's is odd
console.log(5 / 2);
console.log(6 / 2);
You have to parse it to int either using parseInt, or there is a shortcut that you can use as
(s.length / 2 - 1) | 0
const a = 5 / 2;
console.log(parseInt(a));
console.log(a | 0);
const getMiddle = (s) => {
let middle = "";
if (s.length % 2 === 1) middle = [s[(s.length / 2) | 0]];
else middle = [s[(s.length / 2 - 1) | 0], s[(s.length / 2) | 0]];
return middle.join("");
};
console.log(getMiddle("A"));
console.log(getMiddle("HELMO"));
console.log(getMiddle("HELLO0"));
Do not iterate letters. You can simply do it for the even and odd lengths of strings.
const getMiddle = (s) => {
return s[Math.floor(s.length/2)]
}
console.log(getMiddle("abc"));
console.log(getMiddle("abcd"));
console.log(getMiddle("abcde"));
console.log(getMiddle("abcdef"));
console.log(getMiddle("abcdefg"));
You will need to calculate the pivot and the length of the string.
const expect = chai.expect;
class Test {
static assertEquals(actual, expected) {
return expect(actual).to.equal(expected);
}
}
function getMiddle(s) {
const pivot = Math.floor(s.length / 2);
return s.length < 2
? s
: s.length % 2 === 0
? s.substr(pivot - 1, 2)
: s[pivot];
}
mocha.setup('bdd');
describe('GetMiddle', function() {
it('Tests', function() {
Test.assertEquals(getMiddle("test"),"es");
Test.assertEquals(getMiddle("testing"),"t");
Test.assertEquals(getMiddle("middle"),"dd");
Test.assertEquals(getMiddle("A"),"A");
});
});
mocha.run();
<link href="https://cdnjs.cloudflare.com/ajax/libs/mocha/9.1.1/mocha.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/mocha/9.1.1/mocha.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chai/4.3.4/chai.min.js"></script>
<div id="mocha"></div>
Here is my solutions:
function getMiddle(string) {
let middle = Math.floor(string.length / 2);
if (string.length % 2 === 0) {
return string[middle - 1] + string[middle];
}
else{
return string[middle];
}
}
We're looking to:
// find out if the string is even
// take its two middle characters in case it is
// OR
// if the string is odd, take its middle character
A string is even if dividing its length by two leaves no remainder:
s.length % 2 === 0
Now, given this statement, we have two options. One is to return two middle characters in case the string is in fact even.
s.slice(s.length / 2 - 1, s.length. / 2 + 1)
Because if a string is even, its middle is imaginary and the characters we want are one character away from this middle.
If the string is odd in characters, we have an actual middle made up of one character. Therefore, there is an index we can pull.
s[Math.floor(s.length / 2)]
where s has an index which we find by rounding down to the nearest integer the value of the string's length divided by two.
And so:
const getMiddle = s => {
return s.length % 2 === 0
? s.slice(s.length / 2 - 1, s.length / 2 + 1)
: s[Math.floor(s.length / 2)]
}
You can also write this as
const getMiddle = s => s.length % 2 === 0 ? s.slice(s.length / 2 - 1, s.length / 2 + 1) : s[Math.floor(s.length / 2)]

javaScript - Find the sum of all divisors of a given integer

i'm doing some coding exercises and i'm not being able to solve this one.
Find the sum of all divisors of a given integer.
For n = 12, the input should be
sumOfDivisors(n) = 28.
example: 1 + 2 + 3 + 4 + 6 + 12 = 28.
Constraints:
1 ≤ n ≤ 15.
how can i solve this exercise? i'm not being able to.
function(n){
var arr = [],
finalSum;
if(n <= 1 || n => 16){
return false ;
}
for(var i = 0; i < n; i++){
var tmp= n/2;
arr.push(tmp)
// i need to keep on dividing n but i can't get the way of how to
}
return finalSum;
}
This is another way to do it:
var divisors = n=>[...Array(n+1).keys()].slice(1)
.reduce((s, a)=>s+(!(n % a) && a), 0);
console.log(divisors(12));
JSFiddle: https://jsfiddle.net/32n5jdnb/141/
Explaining:
n=> this is an arrow function, the equivalent to function(n) {. You don't need the () if there's only one parameter.
Array(n+1) creates an empty array of n+1 elements
.keys() gets the keys of the empty array (the indexes i.e. 0, 1, 2) so this is a way to create a numeric sequence
[...Array(n+1)].keys()] uses the spread (...) operator to transform the iterator in another array so creating an array with the numeric sequence
.slice(1) removes the first element thus creating a sequence starting with 1. Remember the n+1 ?
.reduce() is a method that iterates though each element and calculates a value in order to reduce the array to one value. It receives as parameter a callback function to calculate the value and the initial value of the calculation
(s, a)=> is the callback function for reduce. It's an arrow function equivalent to function(s, a) {
s+(!(n % a) && a) is the calculation of the value.
s+ s (for sum) or the last value calculated +
!(n % a) this returns true only for the elements that have a 0 as modular value.
(!(n % a) && a) is a js 'trick'. The case is that boolean expressions in javascript don't return true or false. They return a 'truthy' or 'falsy' value which is then converted to boolean. So the actual returned value is the right value for && (considering both have to be truthy) and the first thuthy value found for || (considering only one need to be truthy). So this basically means: if a is a modular value (i.e. != 0) return a to add to the sum, else return 0.
, 0 is the initial value for the reduce calculation.
Reduce documentation: https://developer.mozilla.org/pt-BR/docs/Web/JavaScript/Reference/Global_Objects/Array/Reduce
Edit
Answering to Tristan Forward:
var divisorsList = [];
var divisors = (n)=>[...Array(n+1).keys()].slice(1)
.reduce((s, a)=>{
var divisor = !(n % a) && a;
if (divisor) divisorsList.push(divisor);
return s+divisor;
}, 0);
console.log('Result:', divisors(12));
console.log('Divisors:', divisorsList);
You have to check if specified number is or not a divisor of given integer. You can use modulo % - if there's no rest, specified number is the divisor of the given integer - add it to the sum.
function sumDivisors(num){
var sum = 0;
for (var i = 1; i <= num; i++){
if (!(num % i)) {
sum += i;
}
}
console.log(sum);
}
sumDivisors(6);
sumDivisors(10);
Here is a solution with better algorithm performance (O(sqrt(largest prime factor of n)))
divisors = n => {
sum = 1
for (i = 2; n > 1; i++) {
i * i > n ? i = n : 0
b = 0
while (n % i < 1) {
c = sum * i
sum += c - b
b = c
n /= i
}
}
return sum
}
since n / i is also a devisor this can be done more efficiently.
function sumDivisors(num) {
let sum = 1;
for (let i = 2; i < num / i; i++) {
if (num % i === 0) {
sum += i + num / i;
}
}
const sqrt = Math.sqrt(num);
return num + (num % sqrt === 0 ? sum + sqrt : sum);
}
function countDivisors(n){
let counter = 1;
for(let i=1; i <= n/2; i++){
n % i === 0 ? counter++ : null;
}
return counter
}
in this case, we consider our counter as starting with 1 since by default all numbers are divisible by 1. Then we half the number since numbers that can be able to divide n are less or equal to half its value

How can we get the number of all possible non-negative integers similar to a given non-negative integer by re-arranging it using javascript

Given a non-negative number say 1213, it should return 12 because there are 12 possible integers similar to 1213 i.e., 1123,1132,1213,1231,1312,1321,2113,2131,2311,312,3121 and 3211. Same with 10, it should return 1 and 12 should return 2 and if the number is 120 it should return 4 as combinations are 120,102,210,201.
You can use this formula to get the total number of unique permutations excluding permutations with leading zero.
Lets define some symbols:
n = Total Number of digits
z = Number of zeros
r1, r2, ..., rn = repetition count of digits with count > 1
fact(p) = factorial of number of p
Total permutations = (n - z) * fact(n - 1) / fact(r1) * fact(r2) * .... * fact(rn)
For example, for 1213,
n = 4, z = 0, r1 (digit 1) = 2
permutations = (4 - 0) * fact(4 - 1) / fact(2) = 4 * 6 / 2 = 12
You can easily convert this to program.
function factorial(n) {
if (n <=1)
return 1;
return n * factorial(n-1);
}
function getPermutations(number) {
var n = number.toString().split('').length;
var r = {};
number.toString().split('').forEach(function(digit){
r[digit] = r[digit] || 0;
r[digit] += 1;
});
var z = number.toString().split('').reduce(function(count, digit) {
return (digit === '0') ? count + 1 : count;
}, 0);
var denominator = Object.keys(r).map(function (key) { return r[key]; }).reduce(function(result, curr) {
return result * factorial(curr);
}, 1);
//console.log(n, r, z);
return (n - z) * factorial(n - 1) / denominator;
}
var result = getPermutations(1216);
console.log(result);
Note : This is basic implementation and would not be the most optimum. Also, factorial calculation involves large numbers and would probably fail for large inputs.
You are looking for an anagram algorithm :
This script find every anagram of a string then delete every number starting with zero :
var allAnagrams = function(arr) {
var anagrams = {};
arr.forEach(function(str) {
var recurse = function(ana, str) {
if (str === '')
anagrams[ana] = 1;
for (var i = 0; i < str.length; i++)
recurse(ana + str[i], str.slice(0, i) + str.slice(i + 1));
};
recurse('', str);
});
return Object.keys(anagrams);
}
var arr = ['120']; //declare your number
var anag = allAnagrams(arr); //send it to the function
for (var i in anag) { //delete leading 0
if((anag[i].charAt(0)) === '0' ) {
anag.splice(i);
}
}
console.log(anag); //print array
console.log(anag.length); // print length
Here the output will be :
["102", "120", "201", "210"]
4

How to return an array of values, the sums of which equal a specified number

I'm trying to create an array of numbers of a set length, defining the minimum and a maximum number in the set, and letting a function determine the rest of the numbers between. The kicker is that the sum of this array of numbers must be equal to a predetermined value. The trick is figuring out how that function works.
I found this on stack overflow, which got me the following function:
export const distributeValues = (amount, weights=[]) => {
const distributedAmounts = []
let totalWeights = weights.reduce( (a,b) => a + b)
weights.forEach( weight => {
const weightValue = parseFloat(weight)
const percentage = weightValue / totalWeights
const distributedAmount = Math.round(percentage * amount)
distributedAmounts.push(distributedAmount)
totalWeights -= weightValue
amount -= distributedAmount
})
return distributedAmounts
}
This seems like a good start, but I actually need to work backwards; I'm trying to figure out a function that will give me the weights that would be passed into the above function.
Right now, I have this, a function broken into two parts (apologies for the redundancy):
export const getDistributions = (amount, distributions, modifier) => {
const values = []
let amountLeft = amount;
for (let i = 0; i < distributions; i++ ) {
const value = Math.max(Math.round((amountLeft / (modifier || 4))),1)
amountLeft -= value
values.push(value)
}
// -------------------------------------------- //
// --- correct for cases where total values --- //
// --- end up greater/less than amount --- //
// -------------------------------------------- //
let iterator = 0
let totalAssignedValue = values.reduce((a,b) => a+b);
const lastIndex = (values.length - 1);
const getIndex = (iterator, values) => {
return iterator > lastIndex ? iterator % lastIndex : iterator
}
while (totalAssignedValue > amount) {
iterator = getIndex(iterator)
if (iterator !== lastIndex && iterator !== 0 && values[iterator] > 1) {
values[iterator]--
}
iterator ++
totalAssignedValue = values.reduce((a,b) => a+b);
}
while (totalAssignedValue < amount) {
iterator = getIndex(iterator)
if (iterator !== lastIndex && iterator !== 0) {
values[iterator]++
}
iterator ++
totalAssignedValue = values.reduce((a,b) => a+b);
}
// -------------------------------------------- //
// -------------- end correction -------------- //
// -------------------------------------------- //
return values;
}
The first part tries and distributes the values, but invariably I end up with values that are greater or lesser than the input amount, so there's a second part of the equation that fixes that. Seems a little unclean though, and it's a little arbitrary how the remainders get distributed, so a pure mathematical solution would be great.
I'm starting to wonder if I'm going to need calculus for this, because I basically have the integral (the sum of the array's values), the range of the integral (min and max values), and now have to figure out the formula for the curve. This may be overkill at this point, though.
Thanks for the input!
How about this? First create the set in such way that the first member is the minimum, the second member is minimum + 1, the third minimum + 2, etc. Then sum up the numbers in the set and subtract the sum from the predetermined value. Then distribute the result of the subtraction among all the numbers in the set as outlined betlow.
Set makeSet(int preDet, int min, int max, int setLength)
{
if((max + max - setLength + 1) * setLength / 2 < preDet) return null;
if((min + min + setLength - 1) * setLength / 2 > preDet) return null;
Set set = Set(setLength);
int val = min;
for (int i = 0; i < setLength; i++)
{
set[i] = val++;
}
int sum = (min + val - 1) * setLength / 2;
int dev = preDet - sum;
if(dev)
{
int adj = dev / setLength;
if(dev % setLength) adj++;
for(int i = setLength -1; dev; i--)
{
if(adj > dev) adj = dev;
set[i] += adj;
dev -= adj;
}
}
return set;
}

which are alternative of tofixed() in javascript [duplicate]

Suppose I have a value of 15.7784514, I want to display it 15.77 with no rounding.
var num = parseFloat(15.7784514);
document.write(num.toFixed(1)+"<br />");
document.write(num.toFixed(2)+"<br />");
document.write(num.toFixed(3)+"<br />");
document.write(num.toFixed(10));
Results in -
15.8
15.78
15.778
15.7784514000
How do I display 15.77?
Convert the number into a string, match the number up to the second decimal place:
function calc(theform) {
var num = theform.original.value, rounded = theform.rounded
var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0]
rounded.value = with2Decimals
}
<form onsubmit="return calc(this)">
Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" />
<br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly>
</form>
The toFixed method fails in some cases unlike toString, so be very careful with it.
Update 5 Nov 2016
New answer, always accurate
function toFixed(num, fixed) {
var re = new RegExp('^-?\\d+(?:\.\\d{0,' + (fixed || -1) + '})?');
return num.toString().match(re)[0];
}
As floating point math in javascript will always have edge cases, the previous solution will be accurate most of the time which is not good enough.
There are some solutions to this like num.toPrecision, BigDecimal.js, and accounting.js.
Yet, I believe that merely parsing the string will be the simplest and always accurate.
Basing the update on the well written regex from the accepted answer by #Gumbo, this new toFixed function will always work as expected.
Old answer, not always accurate.
Roll your own toFixed function:
function toFixed(num, fixed) {
fixed = fixed || 0;
fixed = Math.pow(10, fixed);
return Math.floor(num * fixed) / fixed;
}
Another single-line solution :
number = Math.trunc(number*100)/100
I used 100 because you want to truncate to the second digit, but a more flexible solution would be :
number = Math.trunc(number*Math.pow(10, digits))/Math.pow(10, digits)
where digits is the amount of decimal digits to keep.
See Math.trunc specs for details and browser compatibility.
I opted to write this instead to manually remove the remainder with strings so I don't have to deal with the math issues that come with numbers:
num = num.toString(); //If it's not already a String
num = num.slice(0, (num.indexOf("."))+3); //With 3 exposing the hundredths place
Number(num); //If you need it back as a Number
This will give you "15.77" with num = 15.7784514;
Update (Jan 2021)
Depending on its range, a number in javascript may be shown in scientific notation. For example, if you type 0.0000001 in the console, you may see it as 1e-7, whereas 0.000001 appears unchanged (0.000001).
If your application works on a range of numbers for which scientific notation is not involved, you can just ignore this update and use the original answer below.
This update is about adding a function that checks if the number is in scientific format and, if so, converts it into decimal format. Here I'm proposing this one, but you can use any other function that achieves the same goal, according to your application's needs:
function toFixed(x) {
if (Math.abs(x) < 1.0) {
let e = parseInt(x.toString().split('e-')[1]);
if (e) {
x *= Math.pow(10,e-1);
x = '0.' + (new Array(e)).join('0') + x.toString().substring(2);
}
} else {
let e = parseInt(x.toString().split('+')[1]);
if (e > 20) {
e -= 20;
x /= Math.pow(10,e);
x += (new Array(e+1)).join('0');
}
}
return x;
}
Now just apply that function to the parameter (that's the only change with respect to the original answer):
function toFixedTrunc(x, n) {
x = toFixed(x)
// From here on the code is the same than the original answer
const v = (typeof x === 'string' ? x : x.toString()).split('.');
if (n <= 0) return v[0];
let f = v[1] || '';
if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
while (f.length < n) f += '0';
return `${v[0]}.${f}`
}
This updated version addresses also a case mentioned in a comment:
toFixedTrunc(0.000000199, 2) => "0.00"
Again, choose what fits your application needs at best.
Original answer (October 2017)
General solution to truncate (no rounding) a number to the n-th decimal digit and convert it to a string with exactly n decimal digits, for any n≥0.
function toFixedTrunc(x, n) {
const v = (typeof x === 'string' ? x : x.toString()).split('.');
if (n <= 0) return v[0];
let f = v[1] || '';
if (f.length > n) return `${v[0]}.${f.substr(0,n)}`;
while (f.length < n) f += '0';
return `${v[0]}.${f}`
}
where x can be either a number (which gets converted into a string) or a string.
Here are some tests for n=2 (including the one requested by OP):
0 => 0.00
0.01 => 0.01
0.5839 => 0.58
0.999 => 0.99
1.01 => 1.01
2 => 2.00
2.551 => 2.55
2.99999 => 2.99
4.27 => 4.27
15.7784514 => 15.77
123.5999 => 123.59
And for some other values of n:
15.001097 => 15.0010 (n=4)
0.000003298 => 0.0000032 (n=7)
0.000003298257899 => 0.000003298257 (n=12)
parseInt is faster then Math.floor
function floorFigure(figure, decimals){
if (!decimals) decimals = 2;
var d = Math.pow(10,decimals);
return (parseInt(figure*d)/d).toFixed(decimals);
};
floorFigure(123.5999) => "123.59"
floorFigure(123.5999, 3) => "123.599"
num = 19.66752
f = num.toFixed(3).slice(0,-1)
alert(f)
This will return 19.66
Simple do this
number = parseInt(number * 100)/100;
Just truncate the digits:
function truncDigits(inputNumber, digits) {
const fact = 10 ** digits;
return Math.floor(inputNumber * fact) / fact;
}
This is not a safe alternative, as many others commented examples with numbers that turn into exponential notation, that scenery is not covered by this function
// typescript
// function formatLimitDecimals(value: number, decimals: number): number {
function formatLimitDecimals(value, decimals) {
const stringValue = value.toString();
if(stringValue.includes('e')) {
// TODO: remove exponential notation
throw 'invald number';
} else {
const [integerPart, decimalPart] = stringValue.split('.');
if(decimalPart) {
return +[integerPart, decimalPart.slice(0, decimals)].join('.')
} else {
return integerPart;
}
}
}
console.log(formatLimitDecimals(4.156, 2)); // 4.15
console.log(formatLimitDecimals(4.156, 8)); // 4.156
console.log(formatLimitDecimals(4.156, 0)); // 4
console.log(formatLimitDecimals(0, 4)); // 0
// not covered
console.log(formatLimitDecimals(0.000000199, 2)); // 0.00
These solutions do work, but to me seem unnecessarily complicated. I personally like to use the modulus operator to obtain the remainder of a division operation, and remove that. Assuming that num = 15.7784514:
num-=num%.01;
This is equivalent to saying num = num - (num % .01).
I fixed using following simple way-
var num = 15.7784514;
Math.floor(num*100)/100;
Results will be 15.77
My version for positive numbers:
function toFixed_norounding(n,p)
{
var result = n.toFixed(p);
return result <= n ? result: (result - Math.pow(0.1,p)).toFixed(p);
}
Fast, pretty, obvious. (version for positive numbers)
The answers here didn't help me, it kept rounding up or giving me the wrong decimal.
my solution converts your decimal to a string, extracts the characters and then returns the whole thing as a number.
function Dec2(num) {
num = String(num);
if(num.indexOf('.') !== -1) {
var numarr = num.split(".");
if (numarr.length == 1) {
return Number(num);
}
else {
return Number(numarr[0]+"."+numarr[1].charAt(0)+numarr[1].charAt(1));
}
}
else {
return Number(num);
}
}
Dec2(99); // 99
Dec2(99.9999999); // 99.99
Dec2(99.35154); // 99.35
Dec2(99.8); // 99.8
Dec2(10265.985475); // 10265.98
The following code works very good for me:
num.toString().match(/.\*\\..{0,2}|.\*/)[0];
This worked well for me. I hope it will fix your issues too.
function toFixedNumber(number) {
const spitedValues = String(number.toLocaleString()).split('.');
let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
decimalValue = decimalValue.concat('00').substr(0,2);
return '$'+spitedValues[0] + '.' + decimalValue;
}
// 5.56789 ----> $5.56
// 0.342 ----> $0.34
// -10.3484534 ----> $-10.34
// 600 ----> $600.00
function convertNumber(){
var result = toFixedNumber(document.getElementById("valueText").value);
document.getElementById("resultText").value = result;
}
function toFixedNumber(number) {
const spitedValues = String(number.toLocaleString()).split('.');
let decimalValue = spitedValues.length > 1 ? spitedValues[1] : '';
decimalValue = decimalValue.concat('00').substr(0,2);
return '$'+spitedValues[0] + '.' + decimalValue;
}
<div>
<input type="text" id="valueText" placeholder="Input value here..">
<br>
<button onclick="convertNumber()" >Convert</button>
<br><hr>
<input type="text" id="resultText" placeholder="result" readonly="true">
</div>
An Easy way to do it is the next but is necessary ensure that the amount parameter is given as a string.
function truncate(amountAsString, decimals = 2){
var dotIndex = amountAsString.indexOf('.');
var toTruncate = dotIndex !== -1 && ( amountAsString.length > dotIndex + decimals + 1);
var approach = Math.pow(10, decimals);
var amountToTruncate = toTruncate ? amountAsString.slice(0, dotIndex + decimals +1) : amountAsString;
return toTruncate
? Math.floor(parseFloat(amountToTruncate) * approach ) / approach
: parseFloat(amountAsString);
}
console.log(truncate("7.99999")); //OUTPUT ==> 7.99
console.log(truncate("7.99999", 3)); //OUTPUT ==> 7.999
console.log(truncate("12.799999999999999")); //OUTPUT ==> 7.99
Here you are. An answer that shows yet another way to solve the problem:
// For the sake of simplicity, here is a complete function:
function truncate(numToBeTruncated, numOfDecimals) {
var theNumber = numToBeTruncated.toString();
var pointIndex = theNumber.indexOf('.');
return +(theNumber.slice(0, pointIndex > -1 ? ++numOfDecimals + pointIndex : undefined));
}
Note the use of + before the final expression. That is to convert our truncated, sliced string back to number type.
Hope it helps!
truncate without zeroes
function toTrunc(value,n){
return Math.floor(value*Math.pow(10,n))/(Math.pow(10,n));
}
or
function toTrunc(value,n){
x=(value.toString()+".0").split(".");
return parseFloat(x[0]+"."+x[1].substr(0,n));
}
test:
toTrunc(17.4532,2) //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1) //1.4
toTrunc(.4,2) //0.4
truncate with zeroes
function toTruncFixed(value,n){
return toTrunc(value,n).toFixed(n);
}
test:
toTrunc(17.4532,2) //17.45
toTrunc(177.4532,1) //177.4
toTrunc(1.4532,1) //1.4
toTrunc(.4,2) //0.40
If you exactly wanted to truncate to 2 digits of precision, you can go with a simple logic:
function myFunction(number) {
var roundedNumber = number.toFixed(2);
if (roundedNumber > number)
{
roundedNumber = roundedNumber - 0.01;
}
return roundedNumber;
}
I used (num-0.05).toFixed(1) to get the second decimal floored.
It's more reliable to get two floating points without rounding.
Reference Answer
var number = 10.5859;
var fixed2FloatPoints = parseInt(number * 100) / 100;
console.log(fixed2FloatPoints);
Thank You !
My solution in typescript (can easily be ported to JS):
/**
* Returns the price with correct precision as a string
*
* #param price The price in decimal to be formatted.
* #param decimalPlaces The number of decimal places to use
* #return string The price in Decimal formatting.
*/
type toDecimal = (price: number, decimalPlaces?: number) => string;
const toDecimalOdds: toDecimal = (
price: number,
decimalPlaces: number = 2,
): string => {
const priceString: string = price.toString();
const pointIndex: number = priceString.indexOf('.');
// Return the integer part if decimalPlaces is 0
if (decimalPlaces === 0) {
return priceString.substr(0, pointIndex);
}
// Return value with 0s appended after decimal if the price is an integer
if (pointIndex === -1) {
const padZeroString: string = '0'.repeat(decimalPlaces);
return `${priceString}.${padZeroString}`;
}
// If numbers after decimal are less than decimalPlaces, append with 0s
const padZeroLen: number = priceString.length - pointIndex - 1;
if (padZeroLen > 0 && padZeroLen < decimalPlaces) {
const padZeroString: string = '0'.repeat(padZeroLen);
return `${priceString}${padZeroString}`;
}
return priceString.substr(0, pointIndex + decimalPlaces + 1);
};
Test cases:
expect(filters.toDecimalOdds(3.14159)).toBe('3.14');
expect(filters.toDecimalOdds(3.14159, 2)).toBe('3.14');
expect(filters.toDecimalOdds(3.14159, 0)).toBe('3');
expect(filters.toDecimalOdds(3.14159, 10)).toBe('3.1415900000');
expect(filters.toDecimalOdds(8.2)).toBe('8.20');
Any improvements?
Another solution, that truncates and round:
function round (number, decimals, truncate) {
if (truncate) {
number = number.toFixed(decimals + 1);
return parseFloat(number.slice(0, -1));
}
var n = Math.pow(10.0, decimals);
return Math.round(number * n) / n;
};
function limitDecimalsWithoutRounding(val, decimals){
let parts = val.toString().split(".");
return parseFloat(parts[0] + "." + parts[1].substring(0, decimals));
}
var num = parseFloat(15.7784514);
var new_num = limitDecimalsWithoutRounding(num, 2);
Roll your own toFixed function: for positive values Math.floor works fine.
function toFixed(num, fixed) {
fixed = fixed || 0;
fixed = Math.pow(10, fixed);
return Math.floor(num * fixed) / fixed;
}
For negative values Math.floor is round of the values. So you can use Math.ceil instead.
Example,
Math.ceil(-15.778665 * 10000) / 10000 = -15.7786
Math.floor(-15.778665 * 10000) / 10000 = -15.7787 // wrong.
Gumbo's second solution, with the regular expression, does work but is slow because of the regular expression. Gumbo's first solution fails in certain situations due to imprecision in floating points numbers. See the JSFiddle for a demonstration and a benchmark. The second solution takes about 1636 nanoseconds per call on my current system, Intel Core i5-2500 CPU at 3.30 GHz.
The solution I've written involves adding a small compensation to take care of floating point imprecision. It is basically instantaneous, i.e. on the order of nanoseconds. I clocked 2 nanoseconds per call but the JavaScript timers are not very precise or granular. Here is the JS Fiddle and the code.
function toFixedWithoutRounding (value, precision)
{
var factorError = Math.pow(10, 14);
var factorTruncate = Math.pow(10, 14 - precision);
var factorDecimal = Math.pow(10, precision);
return Math.floor(Math.floor(value * factorError + 1) / factorTruncate) / factorDecimal;
}
var values = [1.1299999999, 1.13, 1.139999999, 1.14, 1.14000000001, 1.13 * 100];
for (var i = 0; i < values.length; i++)
{
var value = values[i];
console.log(value + " --> " + toFixedWithoutRounding(value, 2));
}
for (var i = 0; i < values.length; i++)
{
var value = values[i];
console.log(value + " --> " + toFixedWithoutRounding(value, 4));
}
console.log("type of result is " + typeof toFixedWithoutRounding(1.13 * 100 / 100, 2));
// Benchmark
var value = 1.13 * 100;
var startTime = new Date();
var numRun = 1000000;
var nanosecondsPerMilliseconds = 1000000;
for (var run = 0; run < numRun; run++)
toFixedWithoutRounding(value, 2);
var endTime = new Date();
var timeDiffNs = nanosecondsPerMilliseconds * (endTime - startTime);
var timePerCallNs = timeDiffNs / numRun;
console.log("Time per call (nanoseconds): " + timePerCallNs);
Building on David D's answer:
function NumberFormat(num,n) {
var num = (arguments[0] != null) ? arguments[0] : 0;
var n = (arguments[1] != null) ? arguments[1] : 2;
if(num > 0){
num = String(num);
if(num.indexOf('.') !== -1) {
var numarr = num.split(".");
if (numarr.length > 1) {
if(n > 0){
var temp = numarr[0] + ".";
for(var i = 0; i < n; i++){
if(i < numarr[1].length){
temp += numarr[1].charAt(i);
}
}
num = Number(temp);
}
}
}
}
return Number(num);
}
console.log('NumberFormat(123.85,2)',NumberFormat(123.85,2));
console.log('NumberFormat(123.851,2)',NumberFormat(123.851,2));
console.log('NumberFormat(0.85,2)',NumberFormat(0.85,2));
console.log('NumberFormat(0.851,2)',NumberFormat(0.851,2));
console.log('NumberFormat(0.85156,2)',NumberFormat(0.85156,2));
console.log('NumberFormat(0.85156,4)',NumberFormat(0.85156,4));
console.log('NumberFormat(0.85156,8)',NumberFormat(0.85156,8));
console.log('NumberFormat(".85156",2)',NumberFormat(".85156",2));
console.log('NumberFormat("0.85156",2)',NumberFormat("0.85156",2));
console.log('NumberFormat("1005.85156",2)',NumberFormat("1005.85156",2));
console.log('NumberFormat("0",2)',NumberFormat("0",2));
console.log('NumberFormat("",2)',NumberFormat("",2));
console.log('NumberFormat(85156,8)',NumberFormat(85156,8));
console.log('NumberFormat("85156",2)',NumberFormat("85156",2));
console.log('NumberFormat("85156.",2)',NumberFormat("85156.",2));
// NumberFormat(123.85,2) 123.85
// NumberFormat(123.851,2) 123.85
// NumberFormat(0.85,2) 0.85
// NumberFormat(0.851,2) 0.85
// NumberFormat(0.85156,2) 0.85
// NumberFormat(0.85156,4) 0.8515
// NumberFormat(0.85156,8) 0.85156
// NumberFormat(".85156",2) 0.85
// NumberFormat("0.85156",2) 0.85
// NumberFormat("1005.85156",2) 1005.85
// NumberFormat("0",2) 0
// NumberFormat("",2) 0
// NumberFormat(85156,8) 85156
// NumberFormat("85156",2) 85156
// NumberFormat("85156.",2) 85156
Already there are some suitable answer with regular expression and arithmetic calculation, you can also try this
function myFunction() {
var str = 12.234556;
str = str.toString().split('.');
var res = str[1].slice(0, 2);
document.getElementById("demo").innerHTML = str[0]+'.'+res;
}
// output: 12.23
Here is what is did it with string
export function withoutRange(number) {
const str = String(number);
const dotPosition = str.indexOf('.');
if (dotPosition > 0) {
const length = str.substring().length;
const end = length > 3 ? 3 : length;
return str.substring(0, dotPosition + end);
}
return str;
}

Categories