I've got an integer (e.g. 12), and I want to convert it to a floating point number, with a specified number of decimal places.
Draft
function intToFloat(num, decimal) { [code goes here] }
intToFloat(12, 1) // returns 12.0
intToFloat(12, 2) // returns 12.00
// and so on…
What you have is already a floating point number, they're all 64-bit floating point numbers in JavaScript.
To get decimal places when rendering it (as a string, for output), use .toFixed(), like this:
function intToFloat(num, decPlaces) { return num.toFixed(decPlaces); }
You can test it out here (though I'd rename the function, given it's not an accurate description).
toFixed(x) isn't crossed browser solution.
Full solution is following:
function intToFloat(num, decPlaces) { return num + '.' + Array(decPlaces + 1).join('0'); }
If you don't need (or not sure about) fixed number of decimal places, you can just use
xAsString = (Number.isInteger(x)) ? (x + ".0") : (x.toString());
This is relevant in those contexts like, you have an x as 7.0 but x.toString() will give you "7" and you need the string as "7.0". If the x happens to be a float value like say 7.1 or 7.233 then the string should also be "7.1" or "7.233" respectively.
Without using Number.isInteger() :
xAsString = (x % 1 === 0) ? (x + ".0") : (x.toString());
Related
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.
function prec(numb){
var numb_string = numb.toString().split('.')
return numb_string[(numb_string.length - 1)].length
}
function randy(minimum, maximum) {
var most_accurate = Math.max ( prec(minimum), prec(maximum) );
return ( ( Math.random() * ( maximum - minimum ) + minimum ).toFixed( most_accurate ) );
}
// returns random numbers between these points. 1 decimal place of precision:
console.log( randy(2.4,4.4) );
// returns random numbers between these points. 3 decimal places of precision:
console.log( randy(2.443,4.445) );
// returns random numbers between these points. Want 3 decimal places of precision. However, get 0:
console.log( randy(2.000,4.000) );
// Why do I get 0 decimal places? Because floats are rounded into integers automatically:
console.log( 4.0 ); // want 4.0 to be logged. Instead I get '4'
You don't need to read how the functions work. Just the console logs.
Basically, I need to return a random number between two points to a degree of precision. The precision is automatically derived from the most precise float passed to the randy function.
This works fine when the number range is 3.5 3.7 or 34.4322 800.3233 but not 2.0, 3.0 or 4.0000, 5.0000
Then the number is appears to be automatically saved as an integer:
console.log( 2.0 ) //=> 2
I want to extend the Number prototype so that 2.0 is saved as 2.0 so that this function can find the precision:
function prec(numb){
var numb_string = numb.toString().split('.')
return numb_string[(numb_string.length - 1)].length
}
It currently thinks that 3.000000000 has a precision of 0 decimal places because if 3E8 is passed in as the numb parameter, it's read as 3. I want it read as 3.000000000
While I can do this randy(2.toFixed(3),3.toFixed(3)) it gets unreadable and it would be undeniably nicer to do this for smaller precisions: randy(2.000,3.000).
Is this possible?
Fiddle
There is a clever way to solve this problem , is to define a class that helps you managing the number values and the decimal values.
function HappyNumber()
{
this.value = (typeof(arguments[0]) == "number") ? arguments[0] : 0;
this.decimal = (typeof(arguments[1]) == "number") ? arguments[1] : 0;
this.Val = function()
{
return parseFloat(this.value.toFixed(this.decimal));
}
this.toString = function()
{
return (this.value.toFixed(this.decimal)).toString();
}
}
How this class works
Now first thing to do is to create a new number like this
var Num = HappyNumber(4.123545,3);
// first argument is the value
// and second one is decimal
To get the value of your variable, you should use the function Val like this
console.log(Num.Val()); // this one prints 4.123 on your console
The most important part is this one, when you use the toString function it return your number
Num.toString() // it returns "4.123"
(new HappyNumber(4,4)).toString(); // it returns "4.0000"
Now you pass arguments as (HappyNumber), and inside your function use toString and it returns the right value you need and it works with numbers like 1.00 2.000 4.00000
This will do what you want. (Warning: This is probably not a good idea.)
Number.prototype.toString = function () { return this.toFixed(1); }
Normally we expect 0.1+0.2===0.3 to be true. But it is not what javascript will result. As javascript displays decimal floating point number but stores binary floating point number internally. So this returns false.
If we use chrome developer tool console, we'll get the following result:
0.1+0.2;//0.30000000000000004
0.1+1-1;//0.10000000000000009
0.1 + 0.2 === 0.3 ;// returns false but we expect to be true.
0.1+1-1===0.1;//returns false
Due to rounding errors, as a best practice we should not compare non-integers directly. Instead, take an upper bound for rounding errors into consideration. Such an upper bound is called a machine epsilon.
And here is the epsilon method:
var eps = Math.pow(2,-53);
function checkEq(x,y){
return Math.abs(x - y) < eps;
}
Now, if we check it returns true.
checkEq(0.1+0.2,0.3);// returns true
checkEq(0.1+1-1,0.1);//returns true
It's okay and fine. But if I check this:
checkEq(0.3+0.6,0.9);// returns false
Which is not okay and not as what we expect.
So, how should we do to return the correct results?
What I've tried to solve this is like this:
var lx,ly,lxi,lyi;
function isFloating(x){
return x.toString().indexOf('.');
}
function checkEq(x,y){
lxi = x.toString().length - x.toString().indexOf('.') - 1;
lyi = y.toString().length - y.toString().indexOf('.') - 1;
lx = isFloating(x) > -1 ? lxi : 0;
ly = isFloating(y) > -1 ? lyi : 0;
return x.toFixed(lx) - y.toFixed(ly)===0;
}
Now, fixed. And it results fine if I check like this:
checkEq(0.3,0.3); //returns true
But the following returns false
checkEq(0.3+0.6,0.9)
As here first it's value is stored in binaray floating point number and then returning decimal floating point number after calculating.
So now, how can I set toFixed() method for each input like in checkEq(0.3+0.6,0.9) 0.3.toFixed(lx) and 0.6.toFixed(lx) and then only add:
var lx,ly,lxi,lyi;
function isFloating(x){
return x.toString().indexOf('.');
}
function checkEq(x,y){
x = x.toString().split(/\+ | \- | \/ | \ | \\ */);
y = x.toString().split(/\+ | \- | \/ | \ | \\*/);
for(var i=0;i<x.length,y.length;i++){
//here too I may be wrong...
lxi = x[i].toString().length - x[i].toString().indexOf('.') - 1;
lyi = y[i].toString().length - y[i].toString().indexOf('.') - 1;
// particularly after this would wrong...
lx = isFloating(x[i]) > -1 ? lxi : 0;
ly = isFloating(y[i]) > -1 ? lyi : 0;
//And, here I'm stucked too badly...
//take splitted operators to calculate:
//Ex- '0.3 + 1 - 1'
// Number('0.3').toFixed(1) + Number('1').toFixed(0) - Number('1').toFixed(0)
//But careful, we may not know how many input will be there....
}
//return x.toFixed(lx) - y.toFixed(ly)===0;
}
Other answers are also welcome but helping me with my code is greatly appreciated.
Perhaps you should try out some existing JS Math library such as bignumber.js, which supports arbitrary-precision arithmetic. Implementing everything from scratch will be rather time consuming and tedious.
Example
0.3+0.6 //0.8999999999999999
x = new BigNumber('0.3') // "0.3"
y = new BigNumber('0.6') // "0.6"
z = new BigNumber('0.9') // "0.9"
z.equals(x.plus(y)) // true
I think you should take a little larger value for epsilon.
You can also have a look at math.js: the comparison functions of math.js also check for near equality. Comparison is explained here:
http://mathjs.org/docs/datatypes/numbers.html#comparison
So you can do:
math.equal(0.1 + 0.2, 0.3); // true
math.equal(0.3 + 0.6, 0.9); // true
even better, math.js has support for bignumbers (see docs), so you can do:
math.equal(math.bignumber(0.1) + math.bignumber(0.2), math.bignumber(0.3);
or using the expression parser:
math.config({number: 'bignumber'});
math.eval('0.1 + 0.2'); // returns BigNumber 0.3, not 0.30000000000000004
math.eval('0.1 + 0.2 == 0.3'); // returns true
Discontinuous functions such as equality (but also floor and ceil) are badly affected by rounding errors, and taking an epsilon into account may work in some cases, but may also give an incorrect answer (e.g. abs(x-y) < eps may return true while the exact value of x and y are really different); you should do an error analysis to make sure that it is OK. There is no general way to solve the problem in floating point: this depends on your application. If your inputs are decimal numbers and you just use addition, subtraction and multiplication, a decimal floating-point arithmetic may be OK if the precision is large enough so that all your data can be represented exactly. You can also use a rational arithmetic, such as big-rational (not tried).
Is there a nice way to show show decimal numbers with one decimal place all the time but without rounding? So you have the following numbers:
3.55
3.5
3
and I want them to show
3.5
3.5
3.0
you can also use the toFixed() method, though this converts the float to a string.
var float = 3.55
float.toFixed(1);
This will round but rounds down a decimal of 0.5 in any position
Use Math.floor instead.
pad(Math.floor(num * 10) / 10);
where pad adds .0 if it needs to.
Keep in mind that Math.round is probably better. Since 3.55 should be 3.6.
To remove the need for a pad function:
function toOnePlace(n) {
n = ('' + n).split('.');
return n[0] + '.' + (n[1]? n[1].charAt(0) : 0);
}
Try this (where x is your float):
function format_float(float x )
{
if ((x).tostring().contains(".") )
{return parseFloat((x).tostring().Substring(0,indexof(".")+1)) ;}
else
{return x.toFixed(1);}
}
This question already has answers here:
Javascript float comparison
(2 answers)
Closed 6 months ago.
I have this JavaScript function:
Contrl.prototype.EvaluateStatement = function(acVal, cfVal) {
var cv = parseFloat(cfVal).toFixed(2);
var av = parseFloat(acVal).toFixed(2);
if( av < cv) // do some thing
}
When i compare float numbers av=7.00 and cv=12.00 the result of 7.00<12.00 is false!
Any ideas why?
toFixed returns a string, and you are comparing the two resulting strings. Lexically, the 1 in 12 comes before the 7 so 12 < 7.
I guess you want to compare something like:
(Math.round(parseFloat(acVal)*100)/100)
which rounds to two decimals
Compare float numbers with precision:
var precision = 0.001;
if (Math.abs(n1 - n2) <= precision) {
// equal
}
else {
// not equal
}
UPD:
Or, if one of the numbers is precise, compare precision with the relative error
var absoluteError = (Math.abs(nApprox - nExact)),
relativeError = absoluteError / nExact;
return (relativeError <= precision);
The Math.fround() function returns the nearest 32-bit single precision float representation of a Number.
And therefore is one of the best choices to compare 2 floats.
if (Math.fround(1.5) < Math.fround(1.6)) {
console.log('yes')
} else {
console.log('no')
}
>>> yes
// More examples:
console.log(Math.fround(0.9) < Math.fround(1)); >>> true
console.log(Math.fround(1.5) < Math.fround(1.6)); >>> true
console.log(Math.fround(0.005) < Math.fround(0.00006)); >>> false
console.log(Math.fround(0.00000000009) < Math.fround(0.0000000000000009)); >>> false
Comparing floats using short notation, also accepts floats as strings and integers:
var floatOne = 2, floatTwo = '1.456';
Math.floor(floatOne*100) > Math.floor(floatTwo*100)
(!) Note: Comparison happens using integers. What actually happens behind the scenes: 200 > 145
Extend 100 with zero's for more decimal precision. For example use 1000 for 3 decimals precision.
Test:
var floatOne = 2, floatTwo = '1.456';
console.log(Math.floor(floatOne*100), '>', Math.floor(floatTwo*100), '=', Math.floor(floatOne*100) > Math.floor(floatTwo*100));
Comparing of float values is tricky due to long "post dot" tail of the float value stored in the memory. The simplest (and in fact the best) way is: to multiply values, for reducing known amount of post dot digits to zero, and then round the value (to rid of the tail).
Obviously both compared values must be multiplied by the same rate.
F.i.: 1,234 * 1000 gives 1234 - which can be compared very easily. 5,67 can be multiplied by 100, as for reducing the float comparing problem in general, but then it couldn't be compared to the first value (1,234 vel 1234). So in this example it need to be multiplied by 1000.
Then the comparition code could look like (in meta code):
var v1 = 1.234;
var v2 = 5.67;
if (Math.round(v1*1000) < Math.round(v2*1000)) ....