Show numbers to second nearest decimal - javascript

I'm very new to Javascript so please bear with me.
I have this function that adds up a total. How do I make it so that it shows the nearest two decimal places instead of no decimal places?
function calcProdSubTotal() {
var prodSubTotal = 0;
$(".row-total-input").each(function() {
var valString = $(this).val() || 0;
prodSubTotal += parseInt(valString);
});
$("#product-subtotal").val(CommaFormatted(prodSubTotal));
}
Thank you!
Edit: As requested: commaFormatted:
function CommaFormatted(amount) {
var delimiter = ",";
var i = parseInt(amount);
if(isNaN(i)) { return ''; }
i = Math.abs(i);
var minus = '';
if (i < 0) { minus = '-'; }
var n = new String(i);
var a = [];
while(n.length > 3)
{
var nn = n.substr(n.length-3);
a.unshift(nn);
n = n.substr(0,n.length-3);
}
if (n.length > 0) { a.unshift(n); }
n = a.join(delimiter);
amount = "$" + minus + n;
return amount;
}

Well parseInt parses integers, so you are getting rid of any decimals right there. Use parseFloat.
E.g.
parseFloat('10.599').toFixed(2); //10.60
You might also want to change your commaFormatted function to something like:
function commaFormatted(amount) {
if (!isFinite(amount) || typeof amount !== 'number') return '';
return '$' + amount.toFixed(2).replace(/(\d)(?=(\d{3})+(?!\d))/g, '$1,');
}
commaFormatted(0); //$0.00
commaFormatted(1.59); //$1.59
commaFormatted(999999999.99); //$999,999,999.99

Use to function toFixed(2)
The 2 is an integer parameter that says use 2 decimal points, assuming your comma formatted code does not turn it into a string. (If it does, fix the decimals BEFORE you run it through the formatting)
$("#product-subtotal").val(CommaFormatted(parseFloat(prodSubTotal).toFixed(2)));
Remember to parseFloat because the val() could be a string!`

You're looking for toFixed(). It takes one parameter, digits. The parameter is documented as follows:
The number of digits to appear after the decimal point; this may be a value between 0 and 20, inclusive, and implementations may optionally support a larger range of values. If this argument is omitted, it is treated as 0.
Do also note that parseInt() parses integers, truncating any decimals you might have. parseFloat() will preserve decimals as expected.

I solved my problem. I simply changed:
$("#product-subtotal").val(CommaFormatted(prodSubTotal));
to
$("#product-subtotal").val(prodSubTotal);
As I stated in the comments, this was not a script I wrote. It is a script Chris Coyier wrote and I was just trying to amend it. I guess I didn't need to use CommaFormatted for my purposes?
Thank you all for your help!

Related

What is the safest way to split a "Floating Point Number String" into its Whole and Fractional Parts

I have developed the following short function to split a number passed to it in a string format into its Whole and Fractional Parts (also outputted as strings).
Note1: The Whole part of the number can run into large numbers (in excess of 50 digits).
Note 2: The output result (the Whole and the Fraction strings) will not be converted into an integer or a float but will be further manipulated only as a string due to the Javascript rounding for large numbers. So going back to numbers is not a concern here
Because the function detects the machine's locale automatically, it is therefore expected that the user enters (passes) the number in the locale of his local machine or otherwise the number is generated programmatically and passed to the function.
The number is expected to be passed as a "string" due to the very large length and also because there is no handling for numbers passed in exponent (e) format.
The function uses the toLocaleString() to detect the decimal and thousand separators.
I have tested the function with the major number systems (.,' space) and so far, so good.
The question is, how safe will this code be, and are there any alternative better and safer methods to do it or corrections/changes necessary?
Thanks
function splitFloatString(NumString) {
var decimalSeparator = (1.1).toLocaleString().substring(1,2); // Get Decimal Separator
var thousandSeparator = (1000).toLocaleString().substring(1,2); // Get Thousands Separator
NumString += ""; // ensure a string
var fraction ="0"; // default no fractional part
NumString = NumString.replace(RegExp("\\"+thousandSeparator,"g"),""); //remove thousand separators if any
if (RegExp("\\"+decimalSeparator,"g").test(NumString)) { // test for decimal separator
var n = NumString.split(decimalSeparator); // Split at Decimal Seprator
NumString = n[0]; // The Whole part
if (n.length==2) fraction = n[1]; // The Fractional part
if (fraction=="") fraction ="0";
}
console.log("Whole: ("+NumString+"), Fraction: ("+fraction+")"); // added for testing
//return n=[NumString,fraction]; // normal return uncomment
}
//------------------------------------------------------------------------------------
// Tests assuming user's machine and user enters/passes US-EN separators as an example
//------------------------------------------------------------------------------------
splitFloatString("123456789123456699999887788812340786.45678907656912574321115194123123456789");
splitFloatString("1,234,567,891,234,566,999,998,888,812,340.456520754186789075194123123456789");
splitFloatString("200")
splitFloatString("0.")
splitFloatString(123456.2349999)
splitFloatString("")
splitFloatString()
According to me, you are just complicating the whole thing unnecessarily. Here's a simple way to achieve the same result.
function getLocaleSeparators() {
const testNumber = 1000.1.toLocaleString()
return [testNumber.substring(1,2), testNumber.substring(5,6)]
}
function splitFloatString(number) {
const numberString = number.toString()
const [thousandSeparator, decimalSeparator] = getLocaleSeparators()
let [wholePart, fractionPart] = numberString.replace(new RegExp(thousandSeparator, 'g'), '').split(decimalSeparator)
wholePart = wholePart || "0"
fractionPart = fractionPart || "0"
console.log(`Whole: ${wholePart}, Fraction: ${fractionPart}`);
}
function getLocaleSeparators() {
const testNumber = 1000.1.toLocaleString()
return [testNumber.substring(1,2), testNumber.substring(5,6)]
}
function splitFloatString(number) {
const numberString = number.toString()
const [thousandSeparator, decimalSeparator] = getLocaleSeparators()
let [wholePart, fractionPart] = numberString.replace(new RegExp(thousandSeparator, 'g'), '').split(decimalSeparator)
wholePart = wholePart || "0"
fractionPart = fractionPart || "0"
console.log(`Whole: ${wholePart}, Fraction: ${fractionPart}`);
}
splitFloatString("123456789123456699999887788812340786.45678907656912574321115194123123456789");
splitFloatString("1,234,567,891,234,566,999,998,888,812,340.456520754186789075194123123456789");
splitFloatString("200")
splitFloatString("0.")
splitFloatString(123456.2349999)
splitFloatString("")
I recommend you to use the math.floor function for such purposes.
It rounds the number passed as parameter to its nearest integer in downward direction:
Also, The Math.ceil() function rounds a number up to the next largest whole number or integer.
For other handy options, you can check out this https://www.w3docs.com/snippets/javascript/how-to-convert-a-float-number-to-whole-number-in-javascript.html
Please try with this one. might help you.
number = "21212.32323";
var numberString = number + ''; // converts into string
var index = numberString.lastIndexOf("."); // get the index
var strFloat, wholeStr;
if(index === -1) {
strFloat = '';
wholeStr = numberString.replace(/[^\w\s]/gi, '').replace(/ /g,'')
} else {
strFloat = numberString.substring(index + 1); // get the decimal part
var strWhole = numberString.substring(0, index); // get the number
wholeStr = strWhole.replace(/[^\w\s]/gi, '').replace(/ /g,'') // remove spcl character
}
console.log(`Whole: ${wholeStr}, Fraction: ${strFloat}`);
And yes you can not exceed MAX_SAFE_INTEGER in javascript i.e 32-bits.
What is JavaScript's highest integer value that a number can go to without losing precision?
Have been able to finally get the final answer I was looking for.
Thanks to all for their assistance and ideas:
function numberSplit (NumString) {
var decimalSep = 1.1.toLocaleString().substring(1,2), // Get Deciaml Separator
thousandSep = 1e3.toLocaleString().substring(1,2), // Get Thousand Separator
fraction = "0", // Default "0"
n = (NumString = (NumString +="").replace(RegExp("\\"+thousandSep,"g"),"")).split(decimalSep);
NumString = n[0] ; // Get Whole Part
NumString == "" && (NumString = undefined); // Whole = undefined if empty
n.length == 2 && (fraction = n[1]); // Get Fractional part (only if 1 decimal place)
fraction == "" && (fraction = "0"); // Fraction = 0 if empty
console.log("Whole: ("+NumString+"), Fraction: ("+fraction+")")
}
//-----------------------------------------------------------
// Ttests assuming user enters US-EN separators as an example
//-----------------------------------------------------------
numberSplit("123456789123456699999887788812340786.45678907656912574321115194123123456789");
numberSplit("1,234,567,891,234,566,999,998,888,812,340.456520754186789075194123123456789");
numberSplit("200")
numberSplit("0.")
numberSplit(123456.2349999)
numberSplit("1.2.3"); // Fractional part ignored as invalid
numberSplit("") // Return undefined
numberSplit() // Return undefined
numberSplit(NaN) // Return NaN
numberSplit(undefined) // Return undefined

Sum Strings as Numbers

I am trying to solve a kata that seems to be simple on codewars but i seem to not be getting it right.
The instruction for this is as simple as below
Given the string representations of two integers, return the string representation of the sum of those integers.
For example:
sumStrings('1','2') // => '3'
A string representation of an integer will contain no characters besides the ten numerals "0" to "9".
And this is what i have tried
function sumStrings(a,b) {
return ((+a) + (+b)).toString();
}
But the results solves all except two and these are the errors i get
sumStrings('712569312664357328695151392', '8100824045303269669937') - Expected: '712577413488402631964821329', instead got: '7.125774134884027e+26'
sumStrings('50095301248058391139327916261', '81055900096023504197206408605') - Expected: '131151201344081895336534324866', instead got: '1.3115120134408189e+29'
I don't seem to understand where the issues is from. Any help would help thanks.
The value you entered is bigger than the int type max value. You can try changing your code to:
function sumStrings(a,b) {
return ((BigInt(a)) + BigInt(b)).toString();
}
This way it should return the right value
You could pop the digits and collect with a carry over for the next digit.
function add(a, b) {
var aa = Array.from(a, Number),
bb = Array.from(b, Number),
result = [],
carry = 0,
i = Math.max(a.length, b.length);
while (i--) {
carry += (aa.pop() || 0) + (bb.pop() || 0);
result.unshift(carry % 10);
carry = Math.floor(carry / 10);
}
while (carry) {
result.unshift(carry % 10);
carry = Math.floor(carry / 10);
}
return result.join('');
}
console.log(add('712569312664357328695151392', '8100824045303269669937'));
console.log(add('50095301248058391139327916261', '81055900096023504197206408605'));
The problem is that regular javascript integers are not having enough space to store that much big number, So it uses the exponential notation to not lose its precision
what you can do is split each number into parts and add them separately,
one such example is here SO answer
My solution is:
function sumStrings(a,b) {
return BigInt(a) + BigInt(b) + ''
}
Converting from a string to a number or vice versa is not perfect in any language, they will be off by some digits. This doesn't seem to affect small numbers, but it affects big numbers a lot.
The function could go like this.
function sumStrings(a, b) {
return (BigInt(a) + BigInt(b)).toString() // or parseInt for both
}
However, it's still not perfect since if we try to do:
console.log((4213213124214211215421314213.0 + 124214321214213434213124211.0) === sumStrings('4213213124214211215421314213', '124214321214213434213124211'))
The output would be false.

Counting numbers after decimal point in JavaScript

I have a problem in JavaScript. Is it possible to check how many numbers are after the decimal point? I tried to do it using a.toString().split(".")[1]), but if there is no decimal point in the number, there is an error. What should I do if I want the system to do nothing if there is no decimal point?
You're on the right track. You can also .includes('.') to test if it contains a decimal along with .length to return the length of the decimal portion.
function decimalCount (number) {
// Convert to String
const numberAsString = number.toString();
// String Contains Decimal
if (numberAsString.includes('.')) {
return numberAsString.split('.')[1].length;
}
// String Does Not Contain Decimal
return 0;
}
console.log(decimalCount(1.123456789)) // 9
console.log(decimalCount(123456789)) // 0
Convert to a string, split on “.”, then when there is no “.” to split on, assume it’s empty string '' (the part you’re missing), then get said string’s length:
function numDigitsAfterDecimal(x) {
var afterDecimalStr = x.toString().split('.')[1] || ''
return afterDecimalStr.length
}
console.log(numDigitsAfterDecimal(1.23456))
console.log(numDigitsAfterDecimal(0))
You could check if no dot is available, then return zero, otherwise return the delta of the lenght and index with an adjustment.
function getDigits(v) {
var s = v.toString(),
i = s.indexOf('.') + 1;
return i && s.length - i;
}
console.log(getDigits(0));
console.log(getDigits(0.002));
console.log(getDigits(7.654321));
console.log(getDigits(1234567890.654321));
The condition you need is:
number.split('.')[1].length
It checks if there are any numbers after the dot which separates the number from its decimal part.
I'm not sure if you are able to use split on numbers though. If not, parse it to a string.
You first need to convert the decimal number to string and then get the count of character after decimal point,
var a = 10.4578;
var str = a.toString();
if(str){
var val = str.split('.');
if(val && val.length == 2){
alert('Length of number after decimal point is ', val[1].length);
} else {
alert('Not a decimal number');
}
}
The output is 4

Adding Two Decimal Places using JavaScript

Good day Everyone!
I want to know how to return the output with two decimal places. Instead of 10,000 I want it to return 10,000.00. Also I already put .toFixed(2) but it's not working.
When the amount has decimal number other than zero, the values appear on the printout, but when the decimal number has a zero value, the Zeros won't appear on the printout.
Also, I have added a value of Wtax that was pulled-out on a "Bill Credit" Transaction.
Output:
Numeral.js - is a library that you can use for number formatting.
With that you can format your number as follows:
numeral(10000).format('$0,0.00');
Hope this will help you.
You can try this
var x = 1000; // Raw input
x.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,') //returns you 1,000.00
Alternately you can use Netsuite's currency function too
nlapiFormatCurrency('1000'); // returns you 1,000.00
nlapiFormatCurrency('1000.98'); // returns you 1,000.98
You might consider below code. It can round off decimal values based on the decimal places.
This also addresses the issue when rounding off negative values by getting first the absolute value before rounding it off. Without doing that, you will have the following results which the 2nd sample is incorrect.
function roundDecimal(decimalNumber, decimalPlace)
{
//this is to make sure the rounding off is correct even if the decimal is equal to -0.995
var bIsNegative = false;
if (decimalNumber < 0)
{
decimalNumber = Math.abs(decimalNumber);
bIsNegative = true;
}
var fReturn = 0.00;
(decimalPlace == null || decimalPlace == '') ? 0 : decimalPlace;
var multiplierDivisor = Math.pow(10, decimalPlace);
fReturn = Math.round((parseFloat(decimalNumber) * multiplierDivisor).toFixed(decimalPlace)) / multiplierDivisor;
fReturn = (bIsNegative) ? (fReturn * -1) : fReturn;
fReturn = fReturn.toFixed(decimalPlace)
return fReturn;
}
Below are the test sample
And this test sample after addressing the issue for negative values.

How to increment a numeric string by +1 with Javascript/jQuery

I have the following variable:
pageID = 7
I'd like to increment this number on a link:
$('#arrowRight').attr('href', 'page.html?='+pageID);
So this outputs 7, I'd like to append the link to say 8. But if I add +1:
$('#arrowRight').attr('href', 'page.html?='+pageID+1);
I get the following output: 1.html?=71 instead of 8.
How can I increment this number to be pageID+1?
Try this:
parseInt(pageID, 10) + 1
Accordint to your code:
$('#arrowRight').attr('href', 'page.html?='+ (parseInt(pageID, 10) + 1));
+ happens to be valid operator for both strings and numbers that gives different results when both arguments are numeric and when at least one is not. One of possible workarounds is to use operator that only have numeric context but gives same mathematical result, like -. some_var - -1 will always be same as adding 1 to some_var's numeric value, no matter if it is string or not.
$('#arrowRight').attr('href', 'page.html?='+ (pageID - -1));
All these solutions assume that your number you want to add 1 to is within the machine precision for an integer. So if you have a large enough number within that string when you add 1 to it won't change the number.
For Example:
parseInt('800000000000000000', 10) + 1 = 800000000000000000
So I wrote a quick solution to the problem
function addOne(s) {
let newNumber = '';
let continueAdding = true;
for (let i = s.length - 1; i>= 0; i--) {
if (continueAdding) {
let num = parseInt(s[i], 10) + 1;
if (num < 10) {
newNumber += num;
continueAdding = false;
} else {
newNumber += '0';
}
} else {
newNumber +=s[i];
}
}
return newNumber.split("").reverse().join("");
}
Now, using the same example above
addOne('800000000000000000') + 1 = '800000000000000001'
Note that it must stay as a string or you will lose that 1 at the end.
It needs to be a integer, not a string. Try this:
pageID = parseInt(pageID)+1;
Then you can do
$('#arrowRight').attr('href', 'page.html?='+pageID);
Simply, $('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The parentheses makes the calculation done first before string concatenation.
let pageId = '7'
pageId++
console.log(pageId)
Nowadays, you just need to pageID++.
Just change your order of operations by wrapping your addition in parentheses; if pageID is already a number, parseInt() isn't necessary:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
Demo
As long as your pageID is numeric, this should be sufficient:
$('#arrowRight').attr('href', 'page.html?='+(pageID+1));
The problem you were seeing is that JavaScript normally executes in left-to-right order, so the string on the left causes the + to be seen as a concatenator, so it adds the 7 to the string, and then adds 1 to the string including 7.

Categories

Resources