How to decrement decimal values in javascript - javascript

I'm trying to implement a decrement functionality for decimal values in js
On clicking a button the below should happen
1.22 -> 1.21
3.00 -> 2.99
1.2345 -> 1.2344
How could I do that, below is my code
var decimals = 1,
stringC = String(positionData.volume),
value = parseFloat(positionData.volume);
if (stringC.includes(".")) {
const splitted = stringC.split(".");
decimals = splitted[1];
}
const length = decimals?.length;
if (length > 0) {
decimals = "0.";
for (let i = 0; i < length; i++) {
if (i == length - 1) {
decimals += "1";
}
decimals += "0";
}
}
console.log(decimals);
decimals = parseFloat(decimals).toFixed(2);
setCloseValue((value) =>
(parseFloat(value) + decimals).toString()
);
Above is my code but it is appending the values as a string

EDIT: I just realized only decrementing was requested. Oh well - now this answer works for incrementing too... and also steps larger than ±1.
I would solve this as follows:
const input = document.getElementById('input')
function applyStep (step) {
const decimals = input.value.split('.')[1]?.length ?? 0
const stepSize = 10 ** -decimals
input.value = (Number(input.value) + stepSize * step).toFixed(decimals)
}
document.getElementById('increment').addEventListener('click', () => applyStep(1))
document.getElementById('decrement').addEventListener('click', () => applyStep(-1))
<input id="input" value="1.23" />
<button id="increment">Inc</button>
<button id="decrement">Dec</button>
What I do here is this: I first check how many decimals we have after the . (defaulting to 0 if there is no dot).
Then I calculate a step size of 10-decimals, e.g. with 3 decimals we get 10-3 which is 0.001.
Then I add the given step (+1 or -1) multiplied by step size to the numeric value and reformat it with the previous number of decimals before writing it back into the field.
Note that this won't work with numbers that go beyond the precision limits of JavaScripts default number type. If that is desired, a more complicated approach would be needed.
It could be done by handling integer and fractional parts separately as two BigInts, but it needs a lot of thought when it comes to carry and negative values. Here is a possible solution:
const input = document.getElementById('input')
function applyStep (step) {
if (!input.value.match(/^-?\d+(\.\d*)?$/)) throw new Error('Invalid format')
const [strIntegerPart, strFractionalPart = ''] = input.value.split('.')
let bnIntegerPart = BigInt(strIntegerPart)
let bnFractionalPart = BigInt(strFractionalPart)
const decimals = strFractionalPart.length
const maxFractionalPart = 10n ** BigInt(decimals)
let negative = strIntegerPart.startsWith('-') && (bnIntegerPart || bnFractionalPart)
if (negative) {
bnIntegerPart *= -1n
step *= -1n
}
bnFractionalPart += step
const offset = bnFractionalPart < 0n ? maxFractionalPart - 1n : 0n
const carry = (bnFractionalPart - offset) / maxFractionalPart
bnIntegerPart += carry
bnFractionalPart -= carry * maxFractionalPart
if (bnIntegerPart < 0n) {
if (bnFractionalPart) {
bnIntegerPart += 1n
bnFractionalPart = maxFractionalPart - bnFractionalPart
}
bnIntegerPart *= -1n
negative = !negative
}
let newValue = bnIntegerPart.toString()
if (decimals > 0) newValue += '.' + bnFractionalPart.toString().padStart(decimals, '0')
if (negative && (bnIntegerPart || bnFractionalPart)) newValue = '-' + newValue
input.value = newValue
}
document.getElementById('increment').addEventListener('click', () => applyStep(1n))
document.getElementById('decrement').addEventListener('click', () => applyStep(-1n))
<input id="input" value="1.23" />
<button id="increment">Inc</button>
<button id="decrement">Dec</button>
Both these solutions will work with steps other than 1 and -1 too.

const decrementVarable = (decimal)=>{
let decToString = decimal.toString().split('.')
if(decToString.length > 1){
let value = decToString[1]
let number = Number('1'+ '0'.repeat(value.length))
let numWithoutDecimal = ((decimal * number)-1)/number
return numWithoutDecimal
}
return (decimal-1);
}
use this code just pass your decimal

Floating points are usually messy. If you really need it to be 100% precise, use an integer variable, increment that by 1 in each iteration, test for when it reaches 100, and then, for the actual calculation, take your variable and divide it by 100 to obtain the decimal value you need.

Related

JavaScript / reactJS - round up last decimal (without hardcoded decimal to calculate)

By using JavaScript to calculate, For Example (in live can be any value)
1000/0.997 = 1003.0090270812437
By using PC calculator to calculate
1000/0.997 = 1003.009027081244 // auto round up last decimal
But if !!!
this is correct and same as window, in this situation no need round up
500/0.997 = 501.5045135406219 // this is correct and same as window calculator
My prefer output is the auto round up value 1003.009027081244
Question: In JavaScript, how to round up the last digit of decimal?
What I have tried:
Math.round(1003.0090270812437) // 1003
const result = Number((1000/0.997).toPrecision(16))
const result = Number((1000 / 0.997).toPrecision(16))
console.log(result)
Maybe you could use string based solution
Convert a decimal number to string, then split it by the ..
Then take a decimal part length substracted by 1, and use it in toFixed on the original number.
You will probably need some additional checks, to see if there is a decimal part of a number
const decimal = 1003.0090270812437;
const text = decimal.toString().split('.')[1];
console.log(decimal.toFixed(text.length - 1)); // 1003.009027081244
Option 1: playing with numbers and decimals
const countDecimals = value => {
let text = value.toString()
if (text.indexOf('e-') > -1) {
let [base, trail] = text.split('e-')
let deg = parseInt(trail, 10)
return deg - 1
}
if (Math.floor(value) !== value) return value.toString().split(".")[1].length - 1 || 0
return 0
}
const round = number => Math.round(number * Math.pow(10, countDecimals(number - 1))) / Math.pow(10, countDecimals(number - 1))
Option 2: playing with strings
let round = number => {
let str = (number).toString()
let [num, dec] = str.split(".")
let leading_zeros = ""
for (const char of dec) {
if (char !== '0') break
leading_zeros += '0'
}
dec = Math.round(parseFloat(dec.substring(0, dec.length - 1) + "." + dec[dec.length - 1])).toString()
return parseFloat(num + "." + leading_zeros + dec)
}
There is no nice javascript way that I know to achieve this. Due to my knowledge this is the way to go:
Math.round(1003.0090270812437*1000000000000)/1000000000000
Edit:
If you do not want to round to a fixed number of decimals, then I would write a little function to count the given decimals before to know your exponent of 10:
var countDecimals = function(value) {
if (Math.floor(value) !== value)
return value.toString().split(".")[1].length || 0;
return 0;
}
var temp = Math.pow(10, countDecimals-1);
Math.round(1003.0090270812437*temp)/temp;
You can just use toFixed(${Amount of decimals you want to show})
Example:
(2321/912).toFixed(1) will show one fraction of the decimal number
(2322/ 1232).toFixed((2322/ 1232).toString().length - 1 ) will round you up the last digit

Javascript | Floating point numbers + interval loop

I have a floating point number (for example): 0.004178174922295
How could I get the decremental function to make a calculations from this number to 0 in specific amount of time (for example 1 second)?
Thanks.
Expected values:
0.004178174922295
0.004178174922294
0.004178174922293
...
0
As raina77ow and others pointed out in the comments, operations with decimal numbers are problematic in JS, approximations are made and the results may be inexact.
A workaround would be turn the infinitesimals into big integral numbers, work with them and convert them back at the end.
Is this what you were looking for? Please let me know.
EDIT
You can ask for the countdown to be done in a certain amount of time, it does work with reasonable numbers, but in Javascript the minimum interval is of 10 milliseconds, you can't call intervals shorter than that. With the example number you gave, 0.004178174922295, it's like counting down from 4178174922295 to zero. That would requiere almost 1325 years in 10 millisecond intervals (if my math is correct, either way I expect you were going to pass a much shorter lapse).
function infinitesimalCountDown(num, seconds) {
// I create a coeficient to convert the decimal to an int
// Will be a big number starting with "1" and followed by a bunch of zeroes
let coefString = '1';
for(let i=0; i<num.toString().length-2; i++) {
coefString += '0';
}
const coef = Number(coefString);
// This has the digits from the original original but it's an int
let counter = Math.round(num*coef);
// Now I can just treat it as an int and convert it back for the output
const icdInterval = setInterval(() => {
counter--;
console.log(counter/coef);
if(counter <= 0) clearInterval(icdInterval);
}, Math.round(seconds*1000/counter));
}
console.log("It works with a short number");
infinitesimalCountDown(0.0041, 10);
setTimeout(() => {
console.log("It doesn't work with a long number");
infinitesimalCountDown(0.004178174922295, 3000);
}, 12 * 1000);
If you are fine with the steps being the necessary for Javascript to be able to process it, you can do the following:
function infinitesimalCountDown(num, seconds) {
let coefString = '1'
for(let i=0; i<num.toString().length-2; i++) {
coefString += '0'
}
const coef = Number(coefString)
let counter = Math.round(num*coef)
let steps = seconds * 1000 / counter
steps = steps < 100 ? 100 : steps
let step = 1
if(steps == 100) {
step = counter / ((seconds * 1000) / steps)
}
console.log(step)
const icdInterval = setInterval(() => {
counter -= step;
if(counter <= 0) {
counter = 0
clearInterval(icdInterval)
}
console.log(counter/coef)
}, steps)
}
infinitesimalCountDown(0.004178174922295, 5)
If you can represent the input number as number type (so not have many decimals), you can do this using normal number subtraction.
Here, the important thing is to get the unit to be subtracted. You can get the unit using Math.pow.
And from this floating point guide, it is needed to round the counted number and that can be done using toFixed function.
let input = 0.004178174922295;
const decimalCount = input.toString().length - 2;
const unit = Math.pow(10, -1 * decimalCount);
console.log(input);
const loopInterval = setInterval(() => {
input = Number((input - unit).toFixed(decimalCount));
console.log(input);
if (input == 0) {
clearInterval(loopInterval);
}
}, 1000);
And if the input number has many decimals so it is received as string type (not able to present using number type), it is needed to do the subtraction using string as follows.
const input = '0.0041781749222934534534534535';
const inputArr = input.split('.');
const intNum = inputArr[0]; // Present integer
let decimals = inputArr[1]; // Present decimals after '.'
const unit = 1;
function replaceAt(str, index, replace) {
return str.substring(0, index) + replace + str.substring(index + 1);
}
console.log(input);
const loopInterval = setInterval(() => {
let index = decimals.length - 1;
while (parseInt(decimals[index]) < unit) {
decimals = replaceAt(decimals, index --, '9');
}
decimals = replaceAt(decimals, index, `${parseInt(decimals[index]) - unit}`);
console.log(`${intNum}.${decimals}`);
}, 1000);

Is it possible to handle integer overflow without an external library in JavaScript? [duplicate]

This question already has answers here:
What is JavaScript's highest integer value that a number can go to without losing precision?
(21 answers)
Closed 6 years ago.
In Javascript (in Chrome devtools console panel and Node.js v0.12.5), I'm getting an incorrect answer for the product of these two large numbers:
input: 41962049 * 1827116622
output: 76669557221078480
In C++ and C#, I get the correct answer of 76669557221078478 when casting the expression to a 64-bit int.
I'm assuming this is an integer overflow issue, but I certainly could be wrong.
Is there a way to get accurate arithmetic products for large numbers in Javascript without using an external library like BigInteger? This is for an online class that doesn't allow additional libraries.
Thanks for your help.
EDIT: Thanks for the explanation explaining how this isn't actually integer overflow, Patrick Roberts! Very useful.
EDIT 2: jfriend00, I think this question is different than the one you linked to because I am trying to figure out if there is a way to work around JS's limitations without relying on an external library. The answer you provided in the comments helped answer my question, so thank you!
This is not integer overflow, this is due to the limitations of double precision floating point. The highest accurately representable integer in JavaScript is 2^53 due to the epsilon in the range of 2^52 to 2^53 being exactly 1. Above that, integer precision breaks down, but the result of that multiplication is not due to an integer overflow.
Below is the relevant quote from wikipedia on the IEEE 754 standard:
Between 252=4,503,599,627,370,496 and 253=9,007,199,254,740,992 the representable numbers are exactly the integers. For the next range, from 253 to 254, everything is multiplied by 2, so the representable numbers are the even ones, etc. Conversely, for the previous range from 251 to 252, the spacing is 0.5, etc.
The spacing as a fraction of the numbers in the range from 2n to 2n+1 is 2n−52. The maximum relative rounding error when rounding a number to the nearest representable one (the machine epsilon) is therefore 2−53.
To answer your question though, it is very possible. Here is a small library I just wrote in the past couple hours for unsigned integer addition and multiplication that is able to display values in base 10:
class BigUint {
static get WORD() {
return 100000000000000;
}
static get HALF() {
return 10000000;
}
static map(word, index) {
if (index === 0) {
return word.toString();
}
return `000000${word}`.slice(-7);
}
static from(array) {
return Object.create(BigUint.prototype, {
words: {
configurable: true,
enumerable: true,
value: new Uint32Array(array),
writable: true
}
});
}
constructor(number) {
if (/\D/.test(`${number}`)) {
throw new TypeError('seed must be non-negative integer as number or string');
}
this.words = new Uint32Array(`${number}`.split(/(?=(?:.{7})+$)/).map(s => +s));
}
[Symbol.toPrimitive](hint) {
let string = this.toString();
switch (hint) {
case 'number':
return +string;
default:
return string;
}
}
get length() {
return this.words.length;
}
toString() {
return Array.from(this.words).map(BigUint.map).join('');
}
add(that) {
const thisLength = this.length;
const thatLength = that.length;
const maxLength = Math.max(thisLength, thatLength);
const minLength = Math.min(thisLength, thatLength);
const max = maxLength === thisLength ? this : that;
const words = [];
let augend, addend, sum, keep, carry = 0, index;
for (index = 1; index <= minLength; index++) {
augend = this.words[thisLength - index];
addend = that.words[thatLength - index];
sum = augend + addend + carry;
keep = sum % BigUint.HALF;
carry = (sum - keep) / BigUint.HALF;
words.unshift(keep);
}
for (; index <= maxLength; index++) {
sum = max.words[maxLength - index] + carry;
keep = sum % BigUint.HALF;
carry = (sum - keep) / BigUint.HALF;
words.unshift(keep);
}
if (carry > 0) {
words.unshift(carry);
}
return BigUint.from(words);
}
multiply(that) {
const thisLength = this.length;
const thatLength = that.length;
const minLength = Math.min(thisLength, thatLength);
const maxLength = Math.max(thisLength, thatLength);
const min = minLength === thisLength ? this.words : that.words;
const max = maxLength === thatLength ? that.words : this.words;
const partials = [];
let product, words, keep, carry = 0, sum, addend;
for (let outerIndex = minLength - 1; outerIndex >= 0; outerIndex--) {
words = [];
partials.push(words);
for (let j = minLength - 1; j > outerIndex; j--) {
words.unshift(0);
}
for (let innerIndex = maxLength - 1; innerIndex >= 0; innerIndex--) {
product = min[outerIndex] * max[innerIndex] + carry;
keep = product % BigUint.HALF;
carry = (product - keep) / BigUint.HALF;
words.unshift(keep);
}
if (carry > 0) {
words.unshift(carry);
carry = 0;
}
}
sum = BigUint.from(partials.pop());
while (partials.length > 0) {
sum = sum.add(BigUint.from(partials.pop()));
}
return sum;
}
}
const a = document.getElementById('a');
const b = document.getElementById('b');
const c = document.getElementById('c');
const op = document.querySelector('select');
function calculate() {
c.textContent = new BigUint(a.value)[op.value](new BigUint(b.value));
}
document.addEventListener('input', calculate);
calculate();
<input id="a" type="number" min="0" step="1" value="41962049">
<select>
<option value="add">+</option>
<option value="multiply" selected>×</option>
</select>
<input id="b" type="number" min="0" step="1" value="1827116622">
=
<span id="c"></span>

Calculating the maximum value for a decimal using scale and precision

I am working on a JavaScript function that takes two values: precision of a decimal value & scale of a decimal value.
This function should calculate the maximum value that can be stored in a decimal of that size.
For example: a decimal with a precision of 5 and a scale of 3 would have a maximum value of 99.999.
What I have does the job, but it's not elegant. Can anyone think of something more clever?
Also, please forgive the use of this weird version of Hungarian notation.
function maxDecimalValue(pintPrecision, pintScale) {
/* the maximum integers for a decimal is equal to the precision - the scale.
The maximum number of decimal places is equal to the scale.
For example, a decimal(5,3) would have a max value of 99.999
*/
// There's got to be a more elegant way to do this...
var intMaxInts = (pintPrecision- pintScale);
var intMaxDecs = pintScale;
var intCount;
var strMaxValue = "";
// build the max number. Start with the integers.
if (intMaxInts == 0) strMaxValue = "0";
for (intCount = 1; intCount <= intMaxInts; intCount++) {
strMaxValue += "9";
}
// add the values in the decimal place
if (intMaxDecs > 0) {
strMaxValue += ".";
for (intCount = 1; intCount <= intMaxDecs; intCount++) {
strMaxValue += "9";
}
}
return parseFloat(strMaxValue);
}
Haven't tested it:
function maxDecimalValue(precision, scale) {
return Math.pow(10,precision-scale) - Math.pow(10,-scale);
}
precision must be positive
maxDecimalValue(5,3) = 10^(5-3) - 10^-3 = 100 - 1/1000 = 99.999
maxDecimalValue(1,0) = 10^1 - 10^0 = 10 - 1 = 9
maxDecimalValue(1,-1) = 10^(1+1) - 10^1 = 100 - 10 = 90
maxDecimalValue(2,-3) = 10^(2+3) - 10^3 = 100000 - 1000 = 99000
What about
function maxDecimalValue(pintPrecision, pintScale)
{
var result = "";
for(var i = 0; i < pintPrecision; ++i)
{
if(i == (pintPrecision - pintScale)
{
result += ".";
}
result += "9";
}
return parseFloat(result);
}
Check it out here
I would do something along the lines of ((10 * pintPrecision) - 1) + "." + ((10 * pintScale) - 1)
Although pow(10,precision-scale) - pow(10,-scale) is the right formula, you will need to calculate it with decimal type instead of float.
For example, if precision=4 and scale=5, you will get 0.09999000000000001 if it's calculated with float.
Therefore, in Python, you can do something like:
from decimal import Decimal
def calculate_decimal_range(precision: int, scale: int) -> Decimal:
precision, scale = Decimal(precision), Decimal(scale)
return 10**(precision-scale) - 10**-scale

Get decimal portion of a number with JavaScript

I have float numbers like 3.2 and 1.6.
I need to separate the number into the integer and decimal part. For example, a value of 3.2 would be split into two numbers, i.e. 3 and 0.2
Getting the integer portion is easy:
n = Math.floor(n);
But I am having trouble getting the decimal portion.
I have tried this:
remainder = n % 2; //obtem a parte decimal do rating
But it does not always work correctly.
The previous code has the following output:
n = 3.1 // gives remainder = 1.1
What I am missing here?
Use 1, not 2.
js> 2.3 % 1
0.2999999999999998
var decimal = n - Math.floor(n)
Although this won't work for minus numbers so we might have to do
n = Math.abs(n); // Change to positive
var decimal = n - Math.floor(n)
You could convert to string, right?
n = (n + "").split(".");
How is 0.2999999999999998 an acceptable answer? If I were the asker I would want an answer of .3. What we have here is false precision, and my experiments with floor, %, etc indicate that Javascript is fond of false precision for these operations. So I think the answers that are using conversion to string are on the right track.
I would do this:
var decPart = (n+"").split(".")[1];
Specifically, I was using 100233.1 and I wanted the answer ".1".
Here's how I do it, which I think is the most straightforward way to do it:
var x = 3.2;
int_part = Math.trunc(x); // returns 3
float_part = Number((x-int_part).toFixed(2)); // return 0.2
A simple way of doing it is:
var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals); //Returns 0.20000000000000018
Unfortunately, that doesn't return the exact value. However, that is easily fixed:
var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals.toFixed(1)); //Returns 0.2
You can use this if you don't know the number of decimal places:
var x = 3.2;
var decimals = x - Math.floor(x);
var decimalPlaces = x.toString().split('.')[1].length;
decimals = decimals.toFixed(decimalPlaces);
console.log(decimals); //Returns 0.2
Language independent way:
var a = 3.2;
var fract = a * 10 % 10 /10; //0.2
var integr = a - fract; //3
note that it correct only for numbers with one fractioanal lenght )
You can use parseInt() function to get the integer part than use that to extract the decimal part
var myNumber = 3.2;
var integerPart = parseInt(myNumber);
var decimalPart = myNumber - integerPart;
Or you could use regex like:
splitFloat = function(n){
const regex = /(\d*)[.,]{1}(\d*)/;
var m;
if ((m = regex.exec(n.toString())) !== null) {
return {
integer:parseInt(m[1]),
decimal:parseFloat(`0.${m[2]}`)
}
}
}
The following works regardless of the regional settings for decimal separator... on the condition only one character is used for a separator.
var n = 2015.15;
var integer = Math.floor(n).toString();
var strungNumber = n.toString();
if (integer.length === strungNumber.length)
return "0";
return strungNumber.substring(integer.length + 1);
It ain't pretty, but it's accurate.
If precision matters and you require consistent results, here are a few propositions that will return the decimal part of any number as a string, including the leading "0.". If you need it as a float, just add var f = parseFloat( result ) in the end.
If the decimal part equals zero, "0.0" will be returned. Null, NaN and undefined numbers are not tested.
1. String.split
var nstring = (n + ""),
narray = nstring.split("."),
result = "0." + ( narray.length > 1 ? narray[1] : "0" );
2. String.substring, String.indexOf
var nstring = (n + ""),
nindex = nstring.indexOf("."),
result = "0." + (nindex > -1 ? nstring.substring(nindex + 1) : "0");
3. Math.floor, Number.toFixed, String.indexOf
var nstring = (n + ""),
nindex = nstring.indexOf("."),
result = ( nindex > -1 ? (n - Math.floor(n)).toFixed(nstring.length - nindex - 1) : "0.0");
4. Math.floor, Number.toFixed, String.split
var nstring = (n + ""),
narray = nstring.split("."),
result = (narray.length > 1 ? (n - Math.floor(n)).toFixed(narray[1].length) : "0.0");
Here is a jsPerf link: https://jsperf.com/decpart-of-number/
We can see that proposition #2 is the fastest.
A good option is to transform the number into a string and then split it.
// Decimal number
let number = 3.2;
// Convert it into a string
let string = number.toString();
// Split the dot
let array = string.split('.');
// Get both numbers
// The '+' sign transforms the string into a number again
let firstNumber = +array[0]; // 3
let secondNumber = +array[1]; // 2
In one line of code
let [firstNumber, secondNumber] = [+number.toString().split('.')[0], +number.toString().split('.')[1]];
Depending the usage you will give afterwards, but this simple solution could also help you.
Im not saying its a good solution, but for some concrete cases works
var a = 10.2
var c = a.toString().split(".")
console.log(c[1] == 2) //True
console.log(c[1] === 2) //False
But it will take longer than the proposed solution by #Brian M. Hunt
(2.3 % 1).toFixed(4)
I am using:
var n = -556.123444444;
var str = n.toString();
var decimalOnly = 0;
if( str.indexOf('.') != -1 ){ //check if has decimal
var decimalOnly = parseFloat(Math.abs(n).toString().split('.')[1]);
}
Input: -556.123444444
Result: 123444444
You could convert it to a string and use the replace method to replace the integer part with zero, then convert the result back to a number :
var number = 123.123812,
decimals = +number.toString().replace(/^[^\.]+/,'0');
n = Math.floor(x);
remainder = x % 1;
Math functions are faster, but always returns not native expected values.
Easiest way that i found is
(3.2+'').replace(/^[-\d]+\./, '')
The best way to avoid mathematical imprecision is to convert to a string, but ensure that it is in the "dot" format you expect by using toLocaleString:
function getDecimals(n) {
// Note that maximumSignificantDigits defaults to 3 so your decimals will be rounded if not changed.
const parts = n.toLocaleString('en-US', { maximumSignificantDigits: 18 }).split('.')
return parts.length > 1 ? Number('0.' + parts[1]) : 0
}
console.log(getDecimals(10.58))
You can simply use parseInt() function to help, example:
let decimal = 3.2;
let remainder = decimal - parseInt(decimal);
document.write(remainder);
I had a case where I knew all the numbers in question would have only one decimal and wanted to get the decimal portion as an integer so I ended up using this kind of approach:
var number = 3.1,
decimalAsInt = Math.round((number - parseInt(number)) * 10); // returns 1
This works nicely also with integers, returning 0 in those cases.
Although I am very late to answer this, please have a look at the code.
let floatValue = 3.267848;
let decimalDigits = floatValue.toString().split('.')[1];
let decimalPlaces = decimalDigits.length;
let decimalDivider = Math.pow(10, decimalPlaces);
let fractionValue = decimalDigits/decimalDivider;
let integerValue = floatValue - fractionValue;
console.log("Float value: "+floatValue);
console.log("Integer value: "+integerValue);
console.log("Fraction value: "+fractionValue)
I like this answer https://stackoverflow.com/a/4512317/1818723 just need to apply float point fix
function fpFix(n) {
return Math.round(n * 100000000) / 100000000;
}
let decimalPart = 2.3 % 1; //0.2999999999999998
let correct = fpFix(decimalPart); //0.3
Complete function handling negative and positive
function getDecimalPart(decNum) {
return Math.round((decNum % 1) * 100000000) / 100000000;
}
console.log(getDecimalPart(2.3)); // 0.3
console.log(getDecimalPart(-2.3)); // -0.3
console.log(getDecimalPart(2.17247436)); // 0.17247436
P.S. If you are cryptocurrency trading platform developer or banking system developer or any JS developer ;) please apply fpFix everywhere. Thanks!
2021 Update
Optimized version that tackles precision (or not).
// Global variables.
const DEFAULT_PRECISION = 16;
const MAX_CACHED_PRECISION = 20;
// Helper function to avoid numerical imprecision from Math.pow(10, x).
const _pow10 = p => parseFloat(`1e+${p}`);
// Cache precision coefficients, up to a precision of 20 decimal digits.
const PRECISION_COEFS = new Array(MAX_CACHED_PRECISION);
for (let i = 0; i !== MAX_CACHED_PRECISION; ++i) {
PRECISION_COEFS[i] = _pow10(i);
}
// Function to get a power of 10 coefficient,
// optimized for both speed and precision.
const pow10 = p => PRECISION_COEFS[p] || _pow10(p);
// Function to trunc a positive number, optimized for speed.
// See: https://stackoverflow.com/questions/38702724/math-floor-vs-math-trunc-javascript
const trunc = v => (v < 1e8 && ~~v) || Math.trunc(v);
// Helper function to get the decimal part when the number is positive,
// optimized for speed.
// Note: caching 1 / c or 1e-precision still leads to numerical errors.
// So we have to pay the price of the division by c.
const _getDecimals = (v = 0, precision = DEFAULT_PRECISION) => {
const c = pow10(precision); // Get precision coef.
const i = trunc(v); // Get integer.
const d = v - i; // Get decimal.
return Math.round(d * c) / c;
}
// Augmenting Number proto.
Number.prototype.getDecimals = function(precision) {
return (isFinite(this) && (precision ? (
(this < 0 && -_getDecimals(-this, precision))
|| _getDecimals(this, precision)
) : this % 1)) || 0;
}
// Independent function.
const getDecimals = (input, precision) => (isFinite(input) && (
precision ? (
(this < 0 && -_getDecimals(-this, precision))
|| _getDecimals(this, precision)
) : this % 1
)) || 0;
// Tests:
const test = (value, precision) => (
console.log(value, '|', precision, '-->', value.getDecimals(precision))
);
test(1.001 % 1); // --> 0.0009999999999998899
test(1.001 % 1, 16); // --> 0.000999999999999
test(1.001 % 1, 15); // --> 0.001
test(1.001 % 1, 3); // --> 0.001
test(1.001 % 1, 2); // --> 0
test(-1.001 % 1, 16); // --> -0.000999999999999
test(-1.001 % 1, 15); // --> -0.001
test(-1.001 % 1, 3); // --> -0.001
test(-1.001 % 1, 2); // --> 0
After looking at several of these, I am now using...
var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);
Floating-point decimal sign and number format can be dependent from country (.,), so independent solution, which preserved floating point part, is:
getFloatDecimalPortion = function(x) {
x = Math.abs(parseFloat(x));
let n = parseInt(x);
return Number((x - n).toFixed(Math.abs((""+x).length - (""+n).length - 1)));
}
– it is internationalized solution, instead of location-dependent:
getFloatDecimalPortion = x => parseFloat("0." + ((x + "").split(".")[1]));
Solution desription step by step:
parseFloat() for guaranteeing input cocrrection
Math.abs() for avoiding problems with negative numbers
n = parseInt(x) for getting decimal part
x - n for substracting decimal part
We have now number with zero decimal part, but JavaScript could give us additional floating part digits, which we do not want
So, limit additional digits by calling toFixed() with count of digits in floating part of original float number x. Count is calculated as difference between length of original number x and number n in their string representation.
This function splits float number into integers and returns it in array:
function splitNumber(num)
{
num = (""+num).match(/^(-?[0-9]+)([,.][0-9]+)?/)||[];
return [ ~~num[1], +(0+num[2])||0 ];
}
console.log(splitNumber(3.02)); // [ 3, 0.2 ]
console.log(splitNumber(123.456)); // [ 123, 0.456 ]
console.log(splitNumber(789)); // [ 789, 0 ]
console.log(splitNumber(-2.7)); // [ -2, 0.7 ]
console.log(splitNumber("test")); // [ 0, 0 ]
You can extend it to only return existing numbers and null if no number exists:
function splitNumber(num)
{
num = (""+num).match(/^(-?[0-9]+)([,.][0-9]+)?/);
return [ num ? ~~num[1] : null, num && num[2] ? +(0 + num[2]) : null ];
}
console.log(splitNumber(3.02)); // [ 3, 0.02 ]
console.log(splitNumber(123.456)); // [ 123, 0.456 ]
console.log(splitNumber(789)); // [ 789, null ]
console.log(splitNumber(-2.7)); // [ -2, 0.7 ]
console.log(splitNumber("test")); // [ null, null ]
You can also truncate the number
function decimals(val) {
const valStr = val.toString();
const valTruncLength = String(Math.trunc(val)).length;
const dec =
valStr.length != valTruncLength
? valStr.substring(valTruncLength + 1)
: "";
return dec;
}
console.log("decimals: ", decimals(123.654321));
console.log("no decimals: ", decimals(123));
The following function will return an array which will have 2 elements. The first element will be the integer part and the second element will be the decimal part.
function splitNum(num) {
num = num.toString().split('.')
num[0] = Number(num[0])
if (num[1]) num[1] = Number('0.' + num[1])
else num[1] = 0
return num
}
//call this function like this
let num = splitNum(3.2)
console.log(`Integer part is ${num[0]}`)
console.log(`Decimal part is ${num[1]}`)
//or you can call it like this
let [int, deci] = splitNum(3.2)
console.log('Intiger part is ' + int)
console.log('Decimal part is ' + deci)
For example for add two numbers
function add(number1, number2) {
let decimal1 = String(number1).substring(String(number1).indexOf(".") + 1).length;
let decimal2 = String(number2).substring(String(number2).indexOf(".") + 1).length;
let z = Math.max(decimal1, decimal2);
return (number1 * Math.pow(10, z) + number2 * Math.pow(10, z)) / Math.pow(10, z);
}
float a=3.2;
int b=(int)a; // you'll get output b=3 here;
int c=(int)a-b; // you'll get c=.2 value here

Categories

Resources