Javascript round / floor / toFixed on decimals - javascript

I am having an issue with how javascript is dividing and rounding the number.
I have two float , 0.11 and 0.12
I want to calculate the mid of these two numbers and round it to the nearest highest value with 2 decimal price.
For example, if I do this on Calculator
0.11+0.12 / 2 = 0.115, and I need to round it to 0.12 as it is mid or above mid.
If I do this with Javascript, I am not getting an accurate number
Example,
var high = parseFloat(0.12);
var low = parseFloat(0.11);
var mid = (high + low) / 2;
document.getElementById("demo1").innerHTML = mid;
document.getElementById("demo2").innerHTML = mid.toFixed(2);
var another = mid.toFixed(3);
document.getElementById("demo3").innerHTML =another;
var last = Math.floor(another)
document.getElementById("demo4").innerHTML =last;
http://jsfiddle.net/gzqwbp6c/9/
Any input would be appreciated.

As the 0.11499999999999999 shows, the result is very slightly less than 0.115. This is because 0.11 and 0.12 cannot be represented with perfect accuracy using floating-point-numbers.
When you don't want to deal with floating-point-error, it's often easier to work with integers directly. Small integers are represented exactly by floating point numbers.
You can multiply by 100 before, and round, to ensure your numbers are integers, and only divide after you get your final result:
var a = Math.round(100 * parseFloat("0.12")) // 12
var b = Math.round(100 * parseFloat("0.11")) // 11
var mid = (a + b) / 2 // 11.5.
// 0.5 can be represented exactly in floating point for small numbers.
var midRound = (Math.round(mid) / 100).toFixed(2) // "0.12"

Need to multiply (workout on int part, i.e. find mid, and divide to reconvert to origin):
function myMid(high,low, precision){
var precision=2
var convFactor = Math.pow(10,precision);
return
(Math.round((low*convFactor+high*convFactor)/2)/convFactor).toFixed(precision);
}
Float is not precise, you cant rely on that, you'll have unexpected results.

everything *100 to prevent inaccuracies
.toFixed() does the rounding
var a = 0.11;
var b = 0.12;
c = parseFloat((((a*100) + (b*100))/200).toFixed(2));
console.log(c);

Related

Convert repeating decimal to fraction

I am using a button on a JavaScript scientific calculator to convert decimal to fractions via this code:
$('#button-frac').click(function(){
var factor;
// Finds the highest common factor of 2 numbers
function highestCommonFactor() {
for (factor = numerator; factor > 0; factor--) {
if ((numerator % factor == 0) && (denominator % factor == 0)) {
return factor;
}
}
}
// Enter a decimal to convert to a fraction
var decimal = this.form.display.value;
// Split the decimal
var decimalArray = decimal.split(".");
var leftDecimalPart = decimalArray[0];
var rightDecimalPart = decimalArray[1];
// Save decimal part only for later use
var decimalOnly = "0." + rightDecimalPart;
// Find the decimal multiplier
var multiplier = "1";
for (var i = 0; i < rightDecimalPart.length; i++) {
multiplier += "0";
}
// Create numerator by multiplying the multiplier and decimal part together
var numerator = Number(multiplier) * Number(decimalOnly);
var denominator = multiplier;
// Find the highest common factor for the numerator and denominator
highestCommonFactor();
// Simplify the fraction by dividing the numerator and denominator by the factor
var numerator = Number(numerator) / Number(factor);
var denominator = Number(denominator) / Number(factor);
// Output as a mixed number fraction (depending on input)
var mixedNumber = leftDecimalPart + " " + numerator + "/" + denominator;
// Output as a proper fraction or improper fraction (depending on input)
var numerator = numerator + (leftDecimalPart * denominator);
var fraction = numerator + "/" + denominator;
// Display solution in input #disp
$('#disp').val(fraction);
});
This works well, but if the decimal is non-terminating and repeating the script crashes. Any idea how I might remedy this problem? Perhaps there's a way to check if a decimal repeats and to determine the length of the string that repeats, then take that string and express it over a number with equal number of digits, all 9s? Being relatively new to JavaScript, I am at a loss.
Use this and round the decimal after at most 20 repeated chars.
Math.fraction=function(x){
return x?+x?x.toString().includes(".")?x.toString().replace(".","")/(function(a,b){return b?arguments.callee(b,a%b):a;})(x.toString().replace(".",""),"1"+"0".repeat(x.toString().split(".")[1].length))+"/"+("1"+"0".repeat(x.toString().split(".")[1].length))/(function(a,b){return b?arguments.callee(b,a%b):a;})(x.toString().replace(".",""),"1"+"0".repeat(x.toString().split(".")[1].length)):x+"/1":NaN:void 0;
}
Call it with Math.fraction(2.56)
It will:
return NaN if the input is not a number
return undefined if the input is undefined
reduce the fraction
return a string (use Math.fraction(2.56).split("/") for an array containing the numerator and denominator)
Please note that this uses the deprecated arguments.callee, and thus may be incompatible in some browsers.
Test it here

Math.abs() Limit the amount of deimals

I have scoured the internet and I haven't found a solution that really works for me, yet.
var tv = Length * Type;
if (tv < 0)
{
cForm.voltage.value = "-" + Math.abs(tv) + " V";
}
else...
Some of the calculations with these two numbers come out to about the 15th decimal for some reason. I would like to limit the decimal amount that is returned, and NOT allow the number to round up or down. On a calculator it only comes out to about the third decimal, but Math.abs() brings it too far out.
.toFixed() Doesn't work for me because if the number only has 2 decimals it will add additional zeros at the end. I only want to display up to the fourth if it is calculated.
Just expanding on #goto-0 s comment, with the correct # of decimal places.
var tv = Length * Type;
if (tv < 0)
{
cForm.voltage.value = "-" + (Math.round(Math.abs(tv) * 10000) / 10000) + " V";
}
else...
Here's the implementation as a function that truncates the extra decimal places. If you want to round the output you could just use Number.toPrecision().
function toFixedDecimals(num, maxDecimals) {
var multiplier = Math.pow(10, maxDecimals);
return Math.floor(num * multiplier) / multiplier
}
console.log(toFixedDecimals(0.123456789, 4));
console.log(toFixedDecimals(100, 4));
console.log(toFixedDecimals(100.12, 4));
I'm sure its not the most efficient approach but it is pretty brainless -
grab your result
split it into an array based on the decimal point
then trim the decimal part to two digits (or however many you would like).
concat the pieces back together
Sorry for the long variable names - just trying to make it clear what was happening : )
// your starting number - can be whatever you'd like
var number = 145.3928523;
// convert number to string
var number_in_string_form = String(number);
// split the number in an array based on the decimal point
var result = number_in_string_form.split(".");
// this is just to show you what values you end up where in the array
var digit = result[0];
var decimal = result[1];
// trim the decimal lenght to whatever you would like
// starting at the index 0 , take the next 2 characters
decimal = decimal.substr(0, 2);
// concat the digit with the decimal - dont forget the decimal point!
var finished_value = Number(digit + "." + decimal);
In this case the finished_value would = 145.39

Split amount with defined precision and no rounding errors

I needed a way to split an amount (in dollars) between one or more "buckets", for lack of a better word. It needed to have the standard two decimal precision a dollar amount should, but every penny needed to be accounted for.
To illustrate the problem, consider this example:
$200 split 3 ways. If you round down, each amount is $66.66 and you end up 2 cents short, but if you round up, each amount is $66.67 and you're 2 cents over. The answer, of course, is to have one $66.66 and the other two $66.67. That's easy enough for a human to reason, but trying to make bit of JavaScript understand that is kind of a challenge.
Here's the function I came up with:
function SplitTotal( totalAmount, numberToSplit, precision ) {
var precisionFactor = Math.pow(10, precision);
var remainderFactor = 1 / precisionFactor;
var splitAmount = Math.ceil( totalAmount / numberToSplit * precisionFactor ) / precisionFactor;
var remainder = Math.round( (splitAmount * numberToSplit - totalAmount) * precisionFactor ) / precisionFactor;
var result = [];
for (var i = 0; i < numberToSplit; i++) {
result.push( (remainder >= remainderFactor) ?
Math.round( (splitAmount - remainderFactor) * precisionFactor ) / precisionFactor :
splitAmount );
remainder = Math.round( (remainder - remainderFactor) * precisionFactor ) / precisionFactor;
}
return result;
}
The code is a little convoluted, because JavaScript handles floating point numbers atrociously. In order to get a nice, precise decimal amount, you need to multiply the amount by what I call here a "precision factor", which is just some exponent of 10, round the resulting number, and then divide by that precision factor to get back to the original decimal precision.
Even though I only needed 2 decimal spaces of precision, I made the precision easily definable, so this can work for more applications that just dollar amounts. If you want just integers, you can specify a precision of 0.
Ex: $235.38 divided 7 ways:
> SplitTotal(235.38, 7, 2)
[33.62, 33.62, 33.62, 33.63, 33.63, 33.63, 33.63]

How do I get the quotient as int and remainder as a floating point in JavaScript

On my calculator when I do 18/7 I get 2.5714285714285714285714285714286.
From my super limited Math skills 2 is the quotient and .5714285714285714285714285714286 is the remainder.
How can I model this in JavaScript?
Thanks!
var floatingPointPart = (18/7) % 1;
var integerPart = Math.floor(18/7);
Math.floor has the problem of rounding of the result to wrong direction in case of negative number it would be better to use bitwise operation to obtain interger quotients.
var quot = ~~(num/num1)
Hopefully this works for you!
var rawQuotient = 18/7;
var remainder = rawQuotient % 1;
var quotient = rawQuotient - remainder;
In most mathematics, there's no real need for distinction between the fractional portion and the whole portion, especially given that the whole thing can be expressed as a fraction (18/7ths), as a real number, or as a mix of integers and fractions (2 and 4/7ths).
When you get into programming or engineering, or some other derivative, you have definite uses for the separation; but the quotient is really the whole thing, integer and fraction, however you choose to represent that.
We can use simple mathematics to get answer using only / & % operator.
Consider 'num1' as first value & 'num2' as second value. Then :
var Quotient = (num1 - (num1 % num2)) / num2;
var FloatingPoint = (num1 % num2) / num2;
2 is the quotient (or integer part of the result), 4 is the remainder, and 4/7 is the floating point part of the result, which the OP is requesting.
var result = (18/7);
var integerPart = Math.floor(result);
var floatingPointPart = result - integerPart;
integerPart and floatingPointPart are the requested values.
var decimals = float - (float | 0);
In the decimal number 2.5714285714285716,
the quotient, which also is the whole part, is 2
and the decimal/fractional part is 0.5714285714285716 or 0.5714285714285716
but actually, the remainder is 4.000000000000002 or 4
let decimal = 18 / 7;
let quotient = ~~decimal;
let dec_remainder = decimal - quotient;
let dec_remainder0 = decimal % 1;
let remainder = dec_remainder * 7;
let remainder0 = 18 % 7;
document.body.innerHTML = "In the decimal number "+decimal+",<br/>
the quotient, which also is the whole part, is "+quotient+"<br/>
and the decimal/fractional part is "+dec_remainder+ " or " + dec_remainder0 + "<br/>
but actually, the remainder is "+remainder+" or "+remainder0 ;
<!DOCTYPE html>
<html>
<body>
</body>
</html>
You can determine the quotient in several ways.
Actually, 2 is the quotient and 4/18 is the remainder.
Math.divideby= function(d, dby){
var q= Math.floor(d/dby), r= d-(q*dby);
return r== 0? q:q+' and '+r+'/'+d;
}
Math.divideby(18,7)
/* returned value: (String) */
2 and 4/18

How to perform an integer division, and separately get the remainder, in JavaScript?

In JavaScript, how do I get:
The whole number of times a given integer goes into another?
The remainder?
For some number y and some divisor x compute the quotient (quotient)[1] and remainder (remainder) as:
const quotient = Math.floor(y/x);
const remainder = y % x;
Example:
const quotient = Math.floor(13/3); // => 4 => the times 3 fits into 13
const remainder = 13 % 3; // => 1
[1] The integer number resulting from the division of one number by another
I'm no expert in bitwise operators, but here's another way to get the whole number:
var num = ~~(a / b);
This will work properly for negative numbers as well, while Math.floor() will round in the wrong direction.
This seems correct as well:
var num = (a / b) >> 0;
I did some speed tests on Firefox.
-100/3 // -33.33..., 0.3663 millisec
Math.floor(-100/3) // -34, 0.5016 millisec
~~(-100/3) // -33, 0.3619 millisec
(-100/3>>0) // -33, 0.3632 millisec
(-100/3|0) // -33, 0.3856 millisec
(-100-(-100%3))/3 // -33, 0.3591 millisec
/* a=-100, b=3 */
a/b // -33.33..., 0.4863 millisec
Math.floor(a/b) // -34, 0.6019 millisec
~~(a/b) // -33, 0.5148 millisec
(a/b>>0) // -33, 0.5048 millisec
(a/b|0) // -33, 0.5078 millisec
(a-(a%b))/b // -33, 0.6649 millisec
The above is based on 10 million trials for each.
Conclusion: Use (a/b>>0) (or (~~(a/b)) or (a/b|0)) to achieve about 20% gain in efficiency. Also keep in mind that they are all inconsistent with Math.floor, when a/b<0 && a%b!=0.
ES6 introduces the new Math.trunc method. This allows to fix #MarkElliot's answer to make it work for negative numbers too:
var div = Math.trunc(y/x);
var rem = y % x;
Note that Math methods have the advantage over bitwise operators that they work with numbers over 231.
I normally use:
const quotient = (a - a % b) / b;
const remainder = a % b;
It's probably not the most elegant, but it works.
var remainder = x % y;
return (x - remainder) / y;
You can use the function parseInt to get a truncated result.
parseInt(a/b)
To get a remainder, use mod operator:
a%b
parseInt have some pitfalls with strings, to avoid use radix parameter with base 10
parseInt("09", 10)
In some cases the string representation of the number can be a scientific notation, in this case, parseInt will produce a wrong result.
parseInt(100000000000000000000000000000000, 10) // 1e+32
This call will produce 1 as result.
Math.floor(operation) returns the rounded down value of the operation.
Example of 1st question:
const x = 5;
const y = 10.4;
const z = Math.floor(x + y);
console.log(z);
Example of 2nd question:
const x = 14;
const y = 5;
const z = Math.floor(x % y);
console.log(x);
JavaScript calculates right the floor of negative numbers and the remainder of non-integer numbers, following the mathematical definitions for them.
FLOOR is defined as "the largest integer number smaller than the parameter", thus:
positive numbers: FLOOR(X)=integer part of X;
negative numbers: FLOOR(X)=integer part of X minus 1 (because it must be SMALLER than the parameter, i.e., more negative!)
REMAINDER is defined as the "left over" of a division (Euclidean arithmetic). When the dividend is not an integer, the quotient is usually also not an integer, i.e., there is no remainder, but if the quotient is forced to be an integer (and that's what happens when someone tries to get the remainder or modulus of a floating-point number), there will be a non-integer "left over", obviously.
JavaScript does calculate everything as expected, so the programmer must be careful to ask the proper questions (and people should be careful to answer what is asked!) Yarin's first question was NOT "what is the integer division of X by Y", but, instead, "the WHOLE number of times a given integer GOES INTO another". For positive numbers, the answer is the same for both, but not for negative numbers, because the integer division (dividend by divisor) will be -1 smaller than the times a number (divisor) "goes into" another (dividend). In other words, FLOOR will return the correct answer for an integer division of a negative number, but Yarin didn't ask that!
gammax answered correctly, that code works as asked by Yarin. On the other hand, Samuel is wrong, he didn't do the maths, I guess, or he would have seen that it does work (also, he didn't say what was the divisor of his example, but I hope it was 3):
Remainder = X % Y = -100 % 3 = -1
GoesInto = (X - Remainder) / Y = (-100 - -1) / 3 = -99 / 3 = -33
By the way, I tested the code on Firefox 27.0.1, it worked as expected, with positive and negative numbers and also with non-integer values, both for dividend and divisor. Example:
-100.34 / 3.57: GoesInto = -28, Remainder = -0.3800000000000079
Yes, I noticed, there is a precision problem there, but I didn't had time to check it (I don't know if it's a problem with Firefox, Windows 7 or with my CPU's FPU). For Yarin's question, though, which only involves integers, the gammax's code works perfectly.
const idivmod = (a, b) => [a/b |0, a%b];
there is also a proposal working on it
Modulus and Additional Integer Math
Alex Moore-Niemi's comment as an answer:
For Rubyists here from Google in search of divmod, you can implement it as such:
function divmod(x, y) {
var div = Math.trunc(x/y);
var rem = x % y;
return [div, rem];
}
Result:
// [2, 33]
If you need to calculate the remainder for very large integers, which the JS runtime cannot represent as such (any integer greater than 2^32 is represented as a float and so it loses precision), you need to do some trick.
This is especially important for checking many case of check digits which are present in many instances of our daily life (bank account numbers, credit cards, ...)
First of all you need your number as a string (otherwise you have already lost precision and the remainder does not make sense).
str = '123456789123456789123456789'
You now need to split your string in smaller parts, small enough so the concatenation of any remainder and a piece of string can fit in 9 digits.
digits = 9 - String(divisor).length
Prepare a regular expression to split the string
splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g')
For instance, if digits is 7, the regexp is
/.{1,7}(?=(.{7})+$)/g
It matches a nonempty substring of maximum length 7, which is followed ((?=...) is a positive lookahead) by a number of characters that is multiple of 7. The 'g' is to make the expression run through all string, not stopping at first match.
Now convert each part to integer, and calculate the remainders by reduce (adding back the previous remainder - or 0 - multiplied by the correct power of 10):
reducer = (rem, piece) => (rem * Math.pow(10, digits) + piece) % divisor
This will work because of the "subtraction" remainder algorithm:
n mod d = (n - kd) mod d
which allows to replace any 'initial part' of the decimal representation of a number with its remainder, without affecting the final remainder.
The final code would look like:
function remainder(num, div) {
const digits = 9 - String(div).length;
const splitter = new RegExp(`.{1,${digits}}(?=(.{${digits}})+$)`, 'g');
const mult = Math.pow(10, digits);
const reducer = (rem, piece) => (rem * mult + piece) % div;
return str.match(splitter).map(Number).reduce(reducer, 0);
}
If you are just dividing with powers of two, you can use bitwise operators:
export function divideBy2(num) {
return [num >> 1, num & 1];
}
export function divideBy4(num) {
return [num >> 2, num & 3];
}
export function divideBy8(num) {
return [num >> 3, num & 7];
}
(The first is the quotient, the second the remainder)
function integerDivison(dividend, divisor){
this.Division = dividend/divisor;
this.Quotient = Math.floor(dividend/divisor);
this.Remainder = dividend%divisor;
this.calculate = ()=>{
return {Value:this.Division,Quotient:this.Quotient,Remainder:this.Remainder};
}
}
var divide = new integerDivison(5,2);
console.log(divide.Quotient) //to get Quotient of two value
console.log(divide.division) //to get Floating division of two value
console.log(divide.Remainder) //to get Remainder of two value
console.log(divide.calculate()) //to get object containing all the values
You can use ternary to decide how to handle positive and negative integer values as well.
var myInt = (y > 0) ? Math.floor(y/x) : Math.floor(y/x) + 1
If the number is a positive, all is fine. If the number is a negative, it will add 1 because of how Math.floor handles negatives.
This will always truncate towards zero.
Not sure if it is too late, but here it goes:
function intdiv(dividend, divisor) {
divisor = divisor - divisor % 1;
if (divisor == 0) throw new Error("division by zero");
dividend = dividend - dividend % 1;
var rem = dividend % divisor;
return {
remainder: rem,
quotient: (dividend - rem) / divisor
};
}
Calculating number of pages may be done in one step:
Math.ceil(x/y)
Here is a way to do this. (Personally I would not do it this way, but thought it was a fun way to do it for an example) The ways mentioned above are definitely better as this calls multiple functions and is therefore slower as well as takes up more room in your bundle.
function intDivide(numerator, denominator) {
return parseInt((numerator/denominator).toString().split(".")[0]);
}
let x = intDivide(4,5);
let y = intDivide(5,5);
let z = intDivide(6,5);
console.log(x);
console.log(y);
console.log(z);

Categories

Resources