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
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'));
The negative numeric value I'm getting from the back-end application is formatted according to our internal configuration (UI user profile). In other words, for value -23.79879 my xml input may be
<myNumber>-23.79879</myNumber> or <myNumber>23,79879-</myNumber> or other and I can't turn the formatting off. The assumption is that the formats are "standard", normally used for localization.
I'm looking to do something like:
convertStringToNumber(numberString, formatString, slignPosition)
Not sure what you mean with formatString, but maybe something like this?:
function convertStringToNumber(num){
num=num.split(',').join('.');
if(num.indexOf('-') ==num.length-1){
num='-'+num.substr(0,num.length-1);
}
return parseFloat(num) || null;
}
console.log(convertStringToNumber("-23.79879"))
console.log(convertStringToNumber("23,79879-"))
The easiest way to achieve this is to expose the parsing rule from the backend, which obviously knows the format. This can be done in many ways, but one easy way i am fond of is simply to break down all the moving parts of the format, define properties for each on an object and then expose that object to the parser.
The object could look something like this:
var opts = {
thousandsSeparator: ',',
decimalSeparator: '.',
negativeSign: '-'
};
Then pass that object into a parsing function like this:
function parseNumber(opts, str) {
var isNegative = false;
if(str.indexOf(opts.negativeSign) != -1) {
isNegative = true;
str = str.replace(opts.negativeSign,'');
}
var parts = str.split(opts.thousandsSeparator).join('').split(opts.decimalSeparator);
var num = 1 * parts[0];
var deci = 1 * parts[1];
if(deci) num += deci / Math.pow(10,parts[1].length);
return isNegative ? -1 * num : num;
}
You would then call it like thuis:
parseNumber(opts,'2,345.234-'); //-2345.234
sorry i couldn't think of better title ! plus my english sucks
her is my first plugin (basically i repackaged some js code as a plugin )
it adds a comma , separator to value every 3 digit , when someone types something inside textfield
(function($){
$.fn.num = function(userop){
var options = $.extend( {seperator:','} , userop );
$(this).keyup(function(e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace( /\,/g, "");
var x = nStr.split( '.' );
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while ( rgx.test(x1) ) {
x1 = x1.replace( rgx, '$1' + options.seperator + '$2' );
}
$(this).val( x1 + x2 );
})
}
})(jQuery);
$('.number_input').num();
but problem is if i put 123456 in my textfield
var n = $('.number_input').val();
console.log(n);
will return 123,456
which is fine but it suppose to be a numeric value and each time user has to extract commas manually
by running it trough something like
n = Number($.trim(n.replace(/\,/g,'')));
is there any way to add this line to my plugin so it gets executed when someone runs .val() on textfild ?
basically i want to write comma remover once not every single time that i get each effected textfield value
If you change the default .val() method with the combination of the .data(), you'll be able the do what you want. Note that change .val() can have undesired effect (mostly when user try to override .val() aswell...)
Anyway, the first thing to do is give a data to every element that are active number. So in you init, add this code :
this.data('__numered', true);
Now we can detect if the element as a formatting.
Then here come the tricky part : overriding.
You'll have to save the old .val() method :
$.fn.__val = $.fn.val;
Then recreate .val() but check if its a numbered item :
$.fn.val = function(set){
if(typeof set === 'undefined'){
if(this.first().data('__numered'))
return Number($.trim(this.first().__val().replace(/\,/g,'')));
else
return this.first().__val();
}else
return this.__val(set)
}
Fiddle : http://jsfiddle.net/Tw77J/1/
First of all
I think I'm suggesting a better way to do what you are asking, instead of directly answering.
If you use, my solution, your plugin gives the users the option of getting what they want. (You cant predict what users need)
My Solution:
You can add this simple code:
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
So your plugin would become:
(function ($) {
$.fn.num = function (userop) {
if (userop == 'val') {
return Number($.trim($(this).val().replace(/\,/g, '')));
}
var options = $.extend({
seperator: ','
}, userop);
$(this).keyup(function (e) {
var num = $(this).val();
var nStr = num + '';
nStr = nStr.replace(/\,/g, "");
var x = nStr.split('.');
var x1 = x[0];
var x2 = x.length > 1 ? '.' + x[1] : '';
var rgx = /(\d+)(\d{3})/;
while (rgx.test(x1)) {
x1 = x1.replace(rgx, '$1' + options.seperator + '$2');
}
$(this).val(x1 + x2);
});
};
})(jQuery);
Remember, you are the creator of the plugin, and you can impose some rules for the developers using your plugin.
That said, ask your users to use $('selector').num('val'); to get the value without commas, and $('selector').val(), if they want it with comma.
So to brush up:
Use $('selector').num('val'); // with comma
Use $('selector').val(); // without comma
Put that in readme file or any document file.
Live demo!
Also, don't forget me to add me as a contributor to the plugin, If my answer helped you ;)
How do I add the following text boxes together with the logic below?
oneTextBox = $120.00,
twoTextBox = .03*oneTextBox,
threeTextBox = oneTextBox + twoTextBox
I would also like the units of each text box to be in dollars ($).
function doGet(e) {
var app = UiApp.createApplication();
var VertPanel = app.createVerticalPanel().setId('VertPanel');
var oneTextBox = app.createTextBox().setText("$120.00").setId("oneTextBox").setName("oneTextBox");
var twoTextBox = app.createTextBox().setId("twoTextBox").setName("twoTextBox");
var threeTextBox = app.createTextBox().setId("threeTextBox").setName("threeTextBox");
app.add(VertPanel);
VertPanel.add(oneTextBox).add(twoTextBox).add(threeTextBox);
return app;
}
The value returned by e.parameter.oneTextBox in the handler function is a string, in your example it should be "$120.00," and what you want is a numeric value... what I'd suggest is to use a replace() to remove all non numeric characters and convert that to a number like this :
var oneTextBoxNumValue = Number(e.parameter.oneTextBox.replace(/[^0-9]/g,''));// the regex ^0-9 takes everything not between 0 and 9 (and replace by '')
Using the same process on other textBoxes you can do everything you want with math operations after this conversion.
To get the results in $, simply add a '$' to your result
getElementById('oneTextBox').setText(resultNumeric+"$")
the only tricky thing is the decimal point, you'll need to take this into account in your conversion : $120.00, will become 12000 in numeric value so don't forget to divide the result somewhere or your stuff will become very expensive ! ;-)
Also I've had some rounding errors sometimes but it's always possible to handle quite easily, for example in a similar case I had to use something like this to get the correct result : (2.00 instead of 1.99 if quant = 2 in the example below, note that I divide the integer by 100 to get value with 2 decimals)
var total = parseInt(Number(quant)*valtotal*100+0.01)/100;
Hoping it will give some ideas to start with.
EDIT : here is a small code to illustrate :
function calcTest() {
var app = UiApp.createApplication().setTitle('TextField Calculator');
var button = app.createButton('Calculate');
var handler = app.createServerHandler('calc');
button.addClickHandler(handler);
var grid = app.createGrid(5, 2);
grid.setText(0, 0, 'value1 ');
grid.setWidget(0, 1, app.createTextBox().setName('value1').setText('$ 45.00/unit'));
grid.setText(1, 0, 'value2');
grid.setWidget(1, 1, app.createTextBox().setName('value2').setText('3 units'));
grid.setText(2, 0, 'press button to calculate');
grid.setWidget(2, 1, button);
grid.setText(3, 0, 'value3 = value1*1.35');
grid.setWidget(3, 1, app.createTextBox().setId('value3').setEnabled(false));
grid.setText(4, 0,'sum value1 + value2 + value3');
grid.setWidget(4, 1, app.createTextBox().setId('sum').setEnabled(false));
handler.addCallbackElement(grid);
app.add(grid);
var ss = SpreadsheetApp.getActive();
ss.show(app);
}
function calc(e){
var app = UiApp.getActiveApplication();
var value1 = Number(e.parameter.value1.replace(/[^0-9]/g,''))/100;
var value2 = Number(e.parameter.value2.replace(/[^0-9]/g,''));
var calcvalue = parseInt(value1*1.35*100)/100
var sumcalc = calcvalue+value1+value2
app.getElementById('value3').setText('$ '+calcvalue)
app.getElementById('sum').setText(sumcalc+' without unit;)')
return app
}
EDIT 2 : here is another code, a function that I use in an application to convert string values to Euros, it is slightly different in its approach but works pretty well.
function toEuro(val){
if(val==''){temp='';return temp}
var temp = val.toString().replace(/[^\d\.-]/g,'').split('.');
if(temp[0]==''){temp[0]='0'}
if(temp.length==1){var result = temp[0]+',00 €'}
else{
var int = temp[0]
var dec = temp[1]
if(dec.length==1){var result=int+','+dec+'0 €'}else{var result=int+','+dec+' €'}
}
return result
}