how to truncate output values in Nerdamer - javascript

I am using nerdamer.solve to solve roots but the roots are long and not truncated. I wanted to get truncated values upto 4 decimal places. How can I achieve this?
I am using the following code to solve and display output in html:
var r = nerdamer.solve(`1 - ${a} * x^(${p}) + ${b}`, 'x');
document.getElementById("polesAns").innerHTML= r.toString();
The folllowing is output:
[(138655807/135201312)*i+49385501/48155102,(-138655807/135201312)*i+49385501/48155102,(58886197/57419096)*i-49385501/48155102,(-58886197/57419096)*i-49385501/48155102,-560373381/386371730,172668482/119053157,(145619303/100403024)*i-5753750945848186/10000000000000000000000000000000,(-560373381/386371730)*i-5753750945848186/10000000000000000000000000000000]
There is no division performed also.
I tried the solution posted here:
How to use .toFixed() (or any alternative) on Nerdamer.solve solutions?
But how can I do this with my code? I tried the following:
var value = `1 - ${a} * x^(${p}) + ${b}`;
var toFixed = function(value, n) {
var img = Number(nerdamer.imagpart(value).text()).toFixed(n);
var real = Number(nerdamer.realpart(value).text()).toFixed(n);
// Format the number assuming i denotes imaginary in your case
var formatted = '';
if(real !== '0.0000') {
formatted += real;
}
if(img !== '0.0000') {
// Put the plus sign betweent the real and imaginary
if(img.charAt(0) !== '-' && formatted) {
formatted += '+';
}
// Assuming you're using i and not j for instance
formatted += img+'i';
}
return formatted;
};
sol_raw = this.nerdamer.solve(value,'s');
xs = this.nerdamer(sol_raw.toString()).each(function(solution) {
roundedSolutions.push(toFixed(solution, 4));
});
this.setState({
solution: roundedSolution.join(''),
equation:value})
document.getElementById("polesAns").value = solution.toString();
I don't understand the this.setState() part , should i declare sol_raw and xs as var?
Also the substitution of variable is used in the my above root equation from advice here javascript Solving equation with subsitution of variable value
thank you

Related

Operator gets lost when a expression is sent as argument Javascript

I have a simple JS function
let a = 0.33, c=13.89;
var res = calcRound(c*2+calcRound(a*2,1,1),1,1);
console.log(res);
function calcRound(value, figure, padding) {
let val = value;
let result = parseFloat(val);
result = result.toFixed(figure);
return result;
}
It returns a 27.8. But the answer should be 28.5
I have debugged the code. At first, it calculates this and it is correct
calcRound(a*2,1,1) = 0.7
Second time the '+' operator between c*2 and calcRound(a*2,1,1) gets lost.
it becomes like this 27.780.7 which should be like this 27.78+0.7
I know JS first evaluates the expression before sending it as an argument. My question is why the '+' operator is getting omitted?
+ is the concatenator operator in JS, it thinks the result from calcRound() is a string and behaves accordingly.
As mentioned by Andy in the comments, you can see in the
documentation for toFixed()
Return value: A string representing the given number using fixed-point
notation.
Change the return of your function to (to make sure it returns a number):
return Number( result );
let a = 0.33,
c = 13.89;
var res = calcRound(c * 2 + calcRound(a * 2, 1, 1), 1, 1);
console.log(res);
function calcRound(value, figure, padding) {
let val = value;
let result = parseFloat(val);
result = result.toFixed(figure);
return Number(result);
}
It's not getting omitted, JavaScript is treating them like strings and adding 27.78+0.7 as strings, you want to surround them in Number() or parseFloat() statements so that they are treated as numbers.
Like so:
calcRound(parseFloat(c*2) + parseFloat(calcRound(a*2,1,1)),1,1)

Integer and string Javascript

i do a simple exercise "Write a JavaScript program to compute the sum of the two given integers. If the two values are same, then returns triple their sum".
InnerHTML is ok but it seems that my variables are string and not numbers (if i use parseFloat however it doesn't work).
Example : p161 = 10; p162 = 5; => ris = 105 and not 15
let p16 = document.getElementById("p16");
document.getElementById("button16").addEventListener("click", es);
function es(){
let p161 = document.getElementById("input161").value;
let p162 = document.getElementById("input162").value;
let ris = 0;
if (p161 == p162){
ris = (p161 + p162)*3;
return p16.innerHTML = ris;
} else {
ris = p161 + p162;
return p16.innerHTML = ris;
}
}
You are concatenating strings so what you see makes sense. Since you are looking for the sum of integers I dont see why you need to parseFloat. If you want numbers you should just do
let p161 = +document.getElementById("input161").value;
let p162 = +document.getElementById("input162").value;
Plus sign in this case is the unary operator that will convert value to Number type according to ECMA spec

Sum of toFixed not working correctly

I have the following code that calculates and shows the sum of two values.
var oldprice_formated = parseFloat(oldprice).toFixed(2);
var extraPrice = parseFloat(3).toFixed(2);
if(initials != '') {
var new_price = oldprice_formated + extraPrice;
$('.product-detail .woocommerce-Price-amount.amount').html('<span>€</span>'+new_price);
} else {
$('.product-detail .woocommerce-Price amount.amount').html('<span>€</span>'+oldprice_formated);
}
For example:
oldprice_formated = parseFloat(49.99).toFixed(2);
extraPrice = parseFloat(3.00).toFixed(2)
The expected result: Sum is 52.99
Actual result: Sum is 49.003.00
What am I doing wrong? I assume it's with the number parsing, but not sure what I should change to make it work correctly. Thanks!
.toFixed() returns a string, not a number with only two decimal places.
oldprice_formated = parseFloat(49.99).toFixed(2); // "49.99"
extraPrice = parseFloat(3.00).toFixed(2); // "3.00"
When adding those two variables, instead of a number sum, you're concatenating two strings:
"49.99" + "3.00"; // "49.993.00"
I believe this is what you'll want to do:
var new_price = parseFloat(oldprice_formated) + parseFloat(extraPrice);
Or simply run .toFixed() after you sum those values which were already parsed to floats.
Because toFixed() returns a string, the + operator acts as a string concatenator. If you want it to operate as an addition operator, you must typecast your values as numbers:
let oldprice = 49.99;
let oldprice_formatted = parseFloat(oldprice).toFixed(2);
let extraPrice = parseFloat(3).toFixed(2);
console.log(`string concatenation: ${oldprice_formatted + extraPrice}`)
console.log(`type conversion: ${+oldprice_formatted + +extraPrice}`)

Regex to separate thousands with comma and keep two decimals

I recently came up with this code while answering another StackOverflow question. Basically, on blur, this code will properly comma separate by thousands and leave the decimal at two digits (like how USD is written [7,745.56]).
I was wondering if there is more concise way of using regex to , separate and cut off excessive decimal places. I recently updated this post with my most recent attempt. Is there a better way of doing this with regex?
Input -> Target Output
7456 -> 7,456
45345 -> 45,345
25.23523534 -> 25.23
3333.239 -> 3,333.23
234.99 -> 234.99
2300.99 -> 2,300.99
23123123123.22 -> 23,123,123,123.22
Current Regex
var result;
var str = []
reg = new RegExp(/(\d*(\d{2}\.)|\d{1,3})/, "gi");
reversed = "9515321312.2323432".split("").reverse().join("")
while (result = reg.exec(reversed)) {
str.push(result[2] ? result[2] : result[0])
}
console.log(str.join(",").split("").reverse().join("").replace(",.","."))
As an alternative to the Regex, you could use the following approach
Number(num.toFixed(2)).toLocaleString('en-US')
or
num.toLocaleString('en-US', {maximumFractionDigits: 2})
You would still have the toFixed(2), but it's quite clean. toFixed(2) though won't floor the number like you want. Same with {maximumFractionDigits: 2} as the second parameter to toLocaleString as well.
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums)
console.log(num, '->', Number(num.toFixed(2)).toLocaleString('en-US') )
Flooring the number like you showed is a bit tricky. Doing something like (num * 100 | 0) / 100 does not work. The calculation loses precision (e.g. .99 will become .98 in certain situations). (also |0 wouldn't work with larger numbers but even Math.floor() has the precision problem).
The solution would be to treat the numbers like strings.
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
var nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
for (var num of nums) console.log(num, '->', format(num))
function format(num) {
var num = num.toLocaleString('en-US')
var end = num.indexOf('.') < 0 ? num.length : num.indexOf('.') + 3
return num.substring(0, end)
}
(when changing to another format than 'en-US' pay attention to the . in numbers as some languages use a , as fractal separator)
For Compatibility, according to CanIUse toLocaleString('en-US') is
supported in effectively all browsers (since IE6+, Firefox 2+, Chrome
1+ etc)
If you really insist on doing this purely in regex (and truncate instead of round the fractional digits), the only solution I can think of is to use a replacement function as the second argument to .replace():
('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
This makes all your test cases pass:
function format(num){
return ('' + num).replace(
/(\d)(?=(?:\d{3})+(?:\.|$))|(\.\d\d?)\d*$/g,
function(m, s1, s2){
return s2 || (s1 + ',');
}
);
}
test(7456, "7,456");
test(45345, "45,345");
test(25.23523534, "25.23"); //truncated, not rounded
test(3333.239, "3,333.23"); //truncated, not rounded
test(234.99, "234.99");
test(2300.99, "2,300.99");
test(23123123123.22, "23,123,123,123.22");
function test(num, expected){
var actual = format(num);
console.log(num + ' -> ' + expected + ' => ' + actual + ': ' +
(actual === expected ? 'passed' : 'failed')
);
}
I added another layer where regex that drops the unwanted decimals below hundredths on top of your regex comma adding logic;
val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,")
doIt("7456");
doIt("45345");
doIt("25.23523534");
doIt("3333.239");
doIt("234.99");
doIt("2300.99");
doIt("23123123123.22");
doIt("5812090285.2817481974897");
function doIt(val) {
console.log(val + " -> " + val.replace(/(\.\d{2})\d*/, "$1").replace(/(\d)(?=(\d{3})+\b)/g, "$1,"));
}
If multiple calls of regex replace is OK, this answer should satisfy you, since it is only has regex replace logic and nothing else.
Try:
var n = 5812090285.2817481974897;
n = n.toFixed(2).replace(/(\d)(?=(\d{3})+\.)/g, '$1,');
console.log(n);
Outputs:
5,812,090,285.28
Note: .toFixed(2) returns a string. So in order to simplify this further you must add a way to turn n into a string before executing your regex. For example:
n.toString.replace(/(\d)(?=(\d{3})+\.)/g, '$1,'); //ofc with the additional regex
Although you would think it wouldn't matter in javascript, it apparently does in this situation. So I dont know how much 'less' messy it would be to not use.
Here is a way to do it without a regular expression:
value.toLocaleString("en-US", { maximumFractionDigits: 2 })
function formatValue() {
var source = document.getElementById("source");
var output = document.getElementById("output");
var value = parseFloat(source.value);
output.innerText = value.toLocaleString("en-US", { maximumFractionDigits: 2 });
}
<input id="source" type="text" />
<button onclick="formatValue()">Format</button>
<div id="output"></div>
RegEx to rescue again!
My solution has two parts :
.toFixed : Used to limit the decimal limit
/(\d)(?=(\d\d\d)+(?!\d))/g : It makes use of back reference with three digits at a time
Here's everything put together :
// .toFixed((/\./g.test(num)) ? 2 : 0) it tests if the input number has any decimal places, if so limits it to 2 digits and if not, get's rid of it altogether by setting it to 0
num.toFixed((/\./g.test(num)) ? 2 : 0).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
You can see it in action here :
var input = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22]
input.forEach(function(num) {
$('div')
.append(
$('<p>').text(num + ' => ' +
num.toFixed( (/\./g.test(num))?2:0 ).replace(/(\d)(?=(\d\d\d)+(?!\d))/g, "$1,"))
);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div> </div>
NOTE: I've only used jQuery to append the results
You can do like this
(parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
Here just convert number to formatted number with rounded down to 2 decimal places and then remove the .00 if exist.
This can be one approach you can use.
var format = function (num) {
return (parseFloat(num).toFixed(2)).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,").replace(".00","")
}
$(function () {
$("#principalAmtOut").blur(function (e) {
$(this).val(format($(this).val()));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input id="principalAmtOut" type="text" />
You can use Intl.NumberFormat with style set to "decimal" and maximumFractionDigits set to 2 at options object passed at second parameter
const nums = [7456, 45345, 25.23523534, 3333.239, 234.99, 2300.99, 23123123123.22];
const formatOptions = {style:"decimal", maximumFractionDigits:2};
const formatter = new Intl.NumberFormat("en-US", formatOptions);
const formatNums = num => formatter.format(num);
let formattedNums = nums.map(formatNums);
console.log(formattedNums);
I found a solution based on #Pierre's answer without using of toFixed:
function format(n) {
n = +n;
var d = Math.round(n * 100) % 100;
return (Math.floor(n) + '').replace(/(\d)(?=(\d{3})+$)/g, '$1,') + (d > 9 ? '.' + d : d > 0 ? '.0' + d : '');
}
console.log(format(7456));
console.log(format(7456.0));
console.log(format(7456.1));
console.log(format(7456.01));
console.log(format(7456.001));
console.log(format(45345));
console.log(format(25.23523534));
console.log(format(3333.239));
console.log(format(234.99));
console.log(format(2300.99));
console.log(format(23123123123.22));
console.log(format('23123123123.22'));

Sum Big Integers

I'm currently stuck on a Codewars challenge that I can't get my head around:
Given a string representation of two integers, return the string representation of those integers, e.g. sumStrings('1','2') // => '3'
I've used the following code so far, but it fails on large number test cases as the number is converted into a scientific notation:
function sumStrings(a,b) {
var res = +a + +b;
return res.toString();
}
Any help would be much appreciated.
Edit:
Fiddle example: https://jsfiddle.net/ag1z4x7d/
function sumStrings(a, b) { // sum for any length
function carry(value, index) { // cash & carry
if (!value) { // no value no fun
return; // leave shop
}
this[index] = (this[index] || 0) + value; // add value
if (this[index] > 9) { // carry necessary?
carry.bind(this)(this[index] / 10 | 0, index + 1); // better know this & go on
this[index] %= 10; // remind me later
}
}
var array1 = a.split('').map(Number).reverse(), // split stuff and reverse
array2 = b.split('').map(Number).reverse(); // here as well
array1.forEach(carry, array2); // loop baby, shop every item
return array2.reverse().join(''); // return right ordered sum
}
document.write(sumStrings('999', '9') + '<br>');
document.write(sumStrings('9', '999') + '<br>');
document.write(sumStrings('1', '9999999999999999999999999999999999999999999999999999') + '<br>');
The problem is that in that specific kata (IIRC), the numbers stored in a and b are too large for a regular 32 bit integer, and floating point arithmetic isn't exact. Therefore, your version does not return the correct value:
sumStrings('100000000000000000000', '1')
// returns '100000000000000000000' instead of '100000000000000000001'
You have to make sure that this does not happen. One way is to do an good old-fashioned carry-based addition and stay in the digit/character based world throughout the whole computation:
function sumStrings(a, b) {
var digits_a = a.split('')
var digits_b = b.split('')
...
}

Categories

Resources