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.
Related
I'm trying to add all the values of an object into one variable for the total, but I seem to be concatenating them instead?
binance.depth("BNBBTC", (error, depth, symbol) => {
a = 0;
for (value in depth.bids){
a += value;
};
console.log(a);
});
This is the output:
00.001081000.001080900.001080800.001080200.001080000.001079700.001079600.001079100
Any help would be much appreciated
The unexpected behavior of your code is a side effect of adding a String and a Number together. Unlike other languages that complain about adding a Number to a String or vice versa, JavaScript will implicitly convert a Number to a String and not complain at all.
This is discussed in Section 2 of the 2ality Blog Post, JavaScript quirk 1: implicit conversion of values. See below excerpt:
2. Implicit conversion of strings
In web development, you often get values as strings that are actually numbers or booleans. For example, when users enter this kind of data in a form. If you forget to explicitly convert these strings then JavaScript will surprise you negatively in two ways: First, there will be no warning. Second, the values will be converted automatically, but wrongly. The plus operator (+), for instance, is problematic, because it concatenates strings as soon as one of its operands is a string. During the following interaction with JavaScript, the assumption is that we are adding 1 to 5. Instead, we are concatenating the strings '5' and '1'.
> var x = '5'; // wrong assumption: x is a number
> x + 1
> '51'
Incorporating the solution of casting value to a Number, the above code can be rewritten more concisely with the help of ES6. Using Array#reduce() the sum can be modularized a bit. I've also included Error-First Callbacks for Error Handling.
const sumArray = values => values.reduce((sum, value) => (sum + Number(value)), 0)
const getDepth = (data, cb) => {
binance.depth(data, (err, {bids}) => {
if (err) {
return cb(err)
}
return cb(null, sumArray(Object.keys(bids)))
})
}
getDepth('BNBBTC', (err, depth) => {
if (err) {
console.log(err)
} else {
console.log(depth)
}
})
thanks guys
i needed to convert to value to a number first
a += Number(value)
maybe converting value to int such as
var v = parseInt(value);
a += value;
Can not post a comment as my reputation is below 50 :(.
Try converting value to a number before adding: a += Number(value)
All need to do is add a + in front of the string
let a = "10"
let b = "20"
let c = +a + +b //c = 30
In your case:
a += +value
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!
For example, if I produce the factorial of 100 and store it in this way using JavaScript:
function factorial (num) {
if (num == 0) {
return 1;
}
else {
return num * factorial(num - 1);
}
}
var result = factorial(100);
console.log(result) will then produce 9.33262154439441e+157.
Is there a way to have it display in full?
As a string would be fine, but result.toString() literally produces "9.33262154439441e+157".
If there's some way to imitate charAt() for numbers, iterating over each digit and concatenating them as a string would become an option.
All in all, is there any way to achieve this?
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.
I need a round to two number after comma.
example
5000.0000 to 5000
5000.123 to 5000.12
5000.136 to 5000.13
how do this?
I need function x.toFixed(2); but if at the end of two zero, then they should not show
You can use this javascript function to round the number
function roundNumber(rnum, rlength) {
var newnumber = Math.round(rnum*Math.pow(10,rlength))/Math.pow(10,rlength);
return parseFloat(newnumber);
}
var num = roundNumber(5000.0000,0); //will return 5000
As #freakish suggests, toFixed is good idea to round numbers. If you want to floor it, I suggest
parseInt(5000.136*100)/100;
Since x.toFixed(2) returns a string you may do something like this:
function cut(str) {
if (str[str.length-1] == "0")
return str.substr(0, str.length-1);
if (str[str.length-1] == ".")
return str.substr(0, str.length-1);
return str;
}
x = cut(cut(cut(x.toFixed(2))));
Not the most elegant (for example you could add the function to string's prototype), but definetly working.
This link can help you
http://www.w3schools.com/jsref/jsref_tofixed.asp
Example
Convert a number into a string, keeping only two decimals:
var num = 5.56789; var n=num.toFixed(2);
The result of n will be:
5.57