how can I get dynamic precision for float?
exemple what I need :
0.00019400000001.dynamicPrecision() //0.000194
0.0001940001.dynamicPrecision() //0.000194
0.0001941.dynamicPrecision() //0.0001941
0.0194.dynamicPrecision() //0.0194
0.01940000.dynamicPrecision() //0.0194
(its important to not have useless zero at the end)
I can't use toFixed or toPrecision because the significative number can change and is unknow. so what way to write this dynamicPrecision method with dynamic precision?
While it's a bit questionable what you are asking for, one approach would be to take slices of the decimal and then compare it to the original. If it is some threshold percentage different, consider it an answer.
const f = (v, threshold = .9999) => {
let shift = 1;
let part;
do {
shift *= 10;
part = Math.floor(v * shift) / shift;
} while (part / v < threshold);
return part;
}
[0.194, 0.194000001, 0.19401, 0.194101]
.forEach(v => console.log(f(v)));
This uses actual math to determine the significant digit.
Basically, for each step, it takes one more digit and compares it against the value. If it is within the threshold, then it will be returned.
For 1.9410001 it would:
part = 1.9
part = 1.94
part = 1.941 // part / v > threshold, returned
The threshold is then configurable. .9999 means it is 99.99% the same as the original value.
I hope it will help,
var number1 = 0.00019400000001
console.log(parseFloat(number1.toString().replace(/0+[1-9]$/, '')));
You could replace all endings with at least one zero and one one at the end. Then take the numererical value.
function precision(v) {
return +v.toString().replace(/0+1$/, '');
}
console.log([0.00019400000001, 0.0001940001, 0.0001941, 0.0194, 0.01940000].map(precision));
Number.prototype.dynamicPrecision = function(){
return parseFloat(this.valueOf().toString().replace(/0+1$/, ''));
}
console.log(
0.00019400000001.dynamicPrecision(), //0.000194
0.0001940001.dynamicPrecision(), //0.000194
0.0001941.dynamicPrecision(), //0.0001941
0.0194.dynamicPrecision(), //0.0194
0.01940000.dynamicPrecision() //0.0194
)
Related
Generate string from integer with arbitrary base in JavaScript received the following answer:
function parseInt(value, code) {
return [...value].reduce((r, a) => r * code.length + code.indexOf(a), 0);
}
function toString(value, code) {
var digit,
radix= code.length,
result = '';
do {
digit = value % radix;
result = code[digit] + result;
value = Math.floor(value / radix);
} while (value)
return result;
}
console.log(parseInt('dj', 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
console.log(toString(123, 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
console.log(parseInt('a', 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
console.log(toString(0, 'abcdefghijklmnopqrstuvwxyz0123456789+-'));
I am interested something slightly different. Whereas this will generate the shortest code for the number, I would like to now generate a constant-length code based on the number of bits. I am not sure if this is also a complex radix solution as well.
Say I want to generate 8-bit codes using a 16-character alphabet. That means I should be able to take the first 4 bits to select 1 character, and the next 4 bits to select the second character. So I might end up with MV if my 16 character set was ABDHNMOPQRSTUVYZ. Likewise if I had a 16-bit range, I would have 4 character code, and 32-bit range would be an 8-character code. So calling code32(1, 'ABDHNMOPQRSTUVYZ') would give an 8 letter code, while code8(1, 'ABDHNMOPQRSTUVYZ') would give a 2 digit code.
How could that be implemented in JavaScript? Something along these lines?
code8(i, alpha) // 0 to 255 it accepts
code16(i, alpha) // 0 to 65535 it accepts
code32(i, alpha) // 0 to 2^32-1 it accepts
Likewise, how would you get the string code back into the original number (or bit sequence)?
This really comes down to changing toString so that:
It only accepts a code that has a length of a power of 2
It pads the result to a given number of "digits" (characters)
The actual number of digits you would use for a 16 bit number depends on the size of the code. If the code has 16 characters, then it can cover for 4 bits, and so an output of 4 characters would be needed. If however the code has 4 characters, then the output would need 8 characters. You can have cases where the match is not exact, like when you would have a code with 8 characters. Then the output would need 6 characters.
Here I have highlighted the changes to the toString method. My personal preference is to also put the value as last parameter to toString.
function toString(digitCount, code, value) { // <-- add argument digitCount
// Perform a sanity check: code must have a length that is power of 2
if (Math.log2(code.length) % 1) throw "code size not power of 2: " + code.length;
var digit,
radix = code.length,
result = '';
do {
digit = value % radix;
result = code[digit] + result;
value = Math.floor(value / radix);
} while (value)
return result.padStart(digitCount, code[0]); // Pad to the desired output size
}
console.log(toString(4, 'abcdefghijklmnop', 123));
console.log(toString(4, 'abcdefghijklmnop', 0));
console.log(toString(4, 'abcdefghijklmnop', 0xFFFF));
// You could define some more specific functions
const code8 = (code, value) => toString(Math.ceil(8 / Math.log2(code.length)), code, value);
const code16 = (code, value) => toString(Math.ceil(16 / Math.log2(code.length)), code, value);
console.log(code16('abcdefghijklmnop', 123));
console.log(code16('abcdefghijklmnop', 0));
console.log(code16('abcdefghijklmnop', 0xFFFF));
console.log(code8('abcdefghijklmnop', 123));
console.log(code8('abcdefghijklmnop', 0));
console.log(code8('abcdefghijklmnop', 0xFF));
EDIT: I just noticed that you required a decoder as well. It is easy to implement a non-optimal version too, while an optimal one can be implemented via go through each letter and accumulate their value times their weighs.
Is this what you want? I tested this code for bit=16 and bit=8, but when bit=32 the count of codewords becomes too large and hangs the devtools of the browser. It's only a demonstrative code and may need optimization if need to be applied in practical use...
function genCode(len, alpha){
let tmp = [...alpha];
for(let i = 1; i != len; ++i){
const ttmp = [];
tmp.forEach(te => {
[...alpha].forEach(e => {
ttmp.push(te + e);
});
});
tmp = ttmp;
}
return tmp;
}
function code(bits, i, alpha){
const len = Math.ceil(bits / Math.floor(Math.log2(alpha.length)));
return genCode(len, alpha)[i];
}
function decode(bits, c, alpha){
const len = Math.ceil(bits / Math.floor(Math.log2(alpha.length)));
const codes = genCode(len, alpha);
return codes.indexOf(c);
}
console.log(code(16, 2, "ABDHNMOPQRSTUVYZ"));
console.log(decode(16, "AAAD", "ABDHNMOPQRSTUVYZ"));
console.log(code(8, 255, "ABDHNMOPQRSTUVYZ"));
console.log(decode(8, "ZZ", "ABDHNMOPQRSTUVYZ"));
If I have a variable that is set to 2345, and I want to convert it to exponential, I simply do variableName.toExponential().replace(/e+?/, 'e'), which will give me 2.345e3. However, I want it to only return two decimal places there, because otherwise once I get to much larger numbers, like 183947122, I'll get a long decimal, 1.83947122e8. I want this to floor to 1.83e8, but I can't figure out where I would put variable.toFixed(2) in this code.
var a=1233434;
console.log(a.toExponential(2));
you can pass the parameter in .toExponential(2) function for rounding.it will give 2 number after decimal check this link https://www.geeksforgeeks.org/javascript-toexponential-function/
You could calculate the floored value and then apply toExponential.
const f = (x, p) => {
const l = 10 ** (Math.floor(Math.log10(Math.abs(x))) - p);
return (Math.floor(x / l) * l).toExponential(p);
}
console.log(f(183947122, 2));
console.log(f(-183947122, 2));
console.log(f(183947122, 4));
You can do it with a regular expression and replace (which you're already using to replace e+ with e):
const str = variableName.toExponential().replace(/^(\d*\.\d{0,2})\d*e\+(\d+)$/, "$1e$2");
That captures the whole number portion of the coefficient plus up to two fractional digits of it, ignores any others, and captures the full exponent; it replaces the match with $1$2 so you're left with just the up-to-two digits of the coefficient:
function test(variableName) {
const raw = variableName.toExponential();
const str = raw.replace(/^(\d*(?:\.\d{0,2})?)\d*e\+(\d+)$/, "$1e$2");
console.log(variableName, "=>", raw, "=>", str);
}
test(2345);
test(100);
test(1019);
test(183947122);
I have simple function that calculates number of decimals,
eg. _d(0.01) = 2, _d(0.001) = 3 and so on.
We added some new coins to our system that have 0.00000001 quantity and function broke.
Here is why:
0.00000001.toString() = 1e-8, so I cant split it it by '.' and calculate length of second part as I did before.
So the question is - how to get string '0.00000001' out of 0.00000001 number easiest way.
EDIT
I didnt mean exactly '0.00000001', I meant any micronumber to decimal without exp. Some function _d(x) that would work _d(0.000000000012) = '0.000000000012'and so on. What usually toString() does to large (but not too large) numbers.
Use toFixed() with a large number of digits, then count the number of zeroes after the decimal point.
function _d(num) {
var str = num.toFixed(100);
var fraction = str.split('.')[1];
var zeros = fraction.match(/^0*/)[0].length;
return zeros + 1;
}
console.log(_d(0.1));
console.log(_d(0.01));
console.log(_d(0.000000001));
Do you want some thing like this
function decimalPlaces(num) {
var match = (''+num).match(/(?:\.(\d+))?(?:[eE]([+-]?\d+))?$/);
if (!match) { return 0; }
return Math.max(
0,
// Number of digits right of decimal point.
(match[1] ? match[1].length : 0)
// Adjust for scientific notation.
- (match[2] ? +match[2] : 0));
}
console.log(decimalPlaces(0.000000001))
First off, I got some inspiration for this answer from here:
How to avoid scientific notation for large numbers in JavaScript?
You can convert the number to a strong and then check for str.indexOf("e"). If true, then just return the scientific notation part of the string. For example:
function _d() {
// your current function here
if (str.indexOf("e")) {
var something = str.split("-")[1];
return something;
}
}
EDIT: I was working on this before your last comment to me, so this returns a string of the number, which I thought was what you wanted.
Leaving aside the point about significant digits, which is meaningful and correct but does not solve your problem, try this. We take the number, convert to string, if that string is not scientific notation then the answer is trivial. If it is scientific notation, then split the string twice (once on "e-" and then split the zeroth array on "." Add str[1]-1 zeroes to the lead of the number and add the digits to the end.
function _d(arg) {
var str = arg.toString();
if (str.indexOf("e-")) {
var digits = str.split("e-")[0];
var zeroes = str.split("e-")[1];
var zero = Number(zeroes);
var each = digits.split(".");
var something = "0.";
for (var i = 0; i < zeroes-1; i++) {
something += "0";
}
for (var j = 0; j < each.length; j++) {
something = something + each[j];
}
return something;
}
}
This won't work with very large numbers or very small negative numbers. And its pretty convoluted.
The other way is to use .toString() and then look for .length-2(2 characters - '0.'. It should give you the number of zeros.
The advantage of this method is you don't need to know the number of maximum decimals in the number.
To keep it as the full decimal:
Number(0.000001)
// 0.000001
To show it as a string:
0.000001.toFixed(6)
// "0.000001"
Recently I run into the well known floating point precision errors of Javascript. Usually I would avoid floating point calculations on the thin client & rather leave it to the back-end.
I started using the big.js library created by Michael Mclaughlin. Though it has a square-root method/function, it does not have a nth-root methods/function nor does the power function support fraction values as arguments.
So I was wondering if anyone using the library has extended it to have such a function or at least use it to calculate accurate nth-root results.
Michael Mclaughlin suggested that I implement such a function similar in structure to the square-root function. However my attempts at understanding the logic proofed my maths-disability, resulting in simple calculations yielding very wrong results.
Using the algorithm on Rosetta Code also yields incorrect results.
So I was wondering if anyone using the library has extended it to have such a function or at least use it to calculate accurate nth-root results.
Here is the code to my last attempt:
P['nthrt'] = P['nthroot'] = function (n, prec)
{
var negate, r,
x = this,
xc = x['c'],
i = x['s'],
e = x['e'];
// Argument defaults
n = n || 2;
prec = prec || 12;
// Zero?
if ( !xc[0] ) {
return new Big(x)
}
// Negative?
negate = ( n % 2 == 1 && i < 0 );
// Estimate.
r = new Big(1); // Initial guess.
for (var i = 0; i < prec; i++) {
r = (ONE.div(n)).times(r.times(n-1).plus(x.div(r.pow(n-1))));
}
if (negate) r['s'] = -1;
return r;
};
It does not even get obvious results correct like the 4th root of 81 = 3, instead it gets 3.00000000xxx
Newton's method only gives an approximation for the root, so 3.0000xxx should be expected. If you know that the answer should be an integer, you can round r down (Newton's method overestimates the root) and check that r^n=x.
You can use big-numbers library to solve your problem. They support sqrt, pow, exp and many other features.
The pow method accept positive, negative, integer and floating point numbers:
var bn = new BigNumber();
var value = bn.of('81');
var xRoot = value.pow(0.25);
console.log('Result: ' + bn.format(xRoot));
You can use Basenumber.js to perform nth root. Documentation here.
E.g.
// Set precision decimals required
Base.setDecimals(25);
let x = Base("1e+10");
console.log(x.root(10).toString());
<script src='https://cdn.jsdelivr.net/gh/AlexSp3/Basenumber.js#main/BaseNumber.min.js'></script>
Am I missing something here?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Why does .toFixed() return a string?
I want to round the number to 2 decimal digits.
Number.prototype.toFixed is a function designed to format a number before printing it out. It's from the family of toString, toExponential and toPrecision.
To round a number, you would do this:
someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;
// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
.
Or if you want a “native-like” function, you can extend the prototype:
Number.prototype.toFixedNumber = function(digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;
//or even hexadecimal
someNumber = 0xAF309/256; //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";
However, bear in mind that polluting the prototype is considered bad when you're writing a module, as modules shouldn't have any side effects. So, for a module, use the first function.
I've solved this problem by changing this:
someNumber = someNumber.toFixed(2)
...to this:
someNumber = +someNumber.toFixed(2);
However this will convert the number to a string and parse it again, which will have a significant impact on performance. If you care about performance or type safety, check the the other answers as well.
It returns a string because 0.1, and powers thereof (which are used to display decimal fractions), are not representable (at least not with full accuracy) in binary floating-point systems.
For example, 0.1 is really 0.1000000000000000055511151231257827021181583404541015625, and 0.01 is really 0.01000000000000000020816681711721685132943093776702880859375. (Thanks to BigDecimal for proving my point. :-P)
Therefore (absent a decimal floating point or rational number type), outputting it as a string is the only way to get it trimmed to exactly the precision required for display.
Why not use parseFloat?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
I solved it with converting it back to number using JavaScript's Number() function
var x = 2.2873424;
x = Number(x.toFixed(2));
Of course it returns a string. If you wanted to round the numeric variable you'd use Math.round() instead. The point of toFixed is to format the number with a fixed number of decimal places for display to the user.
You can simply use a '+' to convert the result to a number.
var x = 22.032423;
x = +x.toFixed(2); // x = 22.03
May be too late to answer but you can multiple the output with 1 to convert to number again, here is an example.
const x1 = 1211.1212121;
const x2 = x1.toFixed(2)*1;
console.log(typeof(x2));
What would you expect it to return when it's supposed to format a number ? If you have a number you can't pretty much do anything with it because e.g.2 == 2.0 == 2.00 etc. so it has to be a string.
Because its primary use is displaying numbers? If you want to round numbers, use Math.round() with apropriate factors.
To supply an example of why it has to be a string:
If you format 1.toFixed(2) you would get '1.00'.
This is not the same as 1, as 1 does not have 2 decimals.
I know JavaScript isn't exactly a performance language, but chances are you'd get better performance for a rounding if you use something like:
roundedValue = Math.round(value * 100) * 0.01
You should use it like below.
var someNumber: number = 0.000000;
someNumber = Number(someNumber.toFixed(2))
Why not * the result by 1 i.e
someNumber.toFixed(2) * 1
Here's a slightly more functional version of the answer m93a provided.
const toFixedNumber = (toFixTo = 2, base = 10) => num => {
const pow = Math.pow(base, toFixTo)
return +(Math.round(num * pow) / pow)
}
const oneNumber = 10.12323223
const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123
// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12
For others like me that happen upon this very old question, a modern solution:
const roundValue = (num, decimals = 2) => {
let scaling = 10 ** decimals;
return Math.round((num + Number.EPSILON) * scaling) / scaling;
}
ref: https://stackoverflow.com/a/11832950
Be careful using toFixed() and Math.round(), they can produce unexpected results due to the floating point number system:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
console.log(toFixedNumber(130.795, 2, 10));
// 130.79 (incorrect)
console.log(toFixedNumber(100.795, 2, 10));
// 100.8
console.log(+130.795.toFixed(2));
// 130.79 (incorrect)
console.log(+100.795.toFixed(2));
// 100.8
I recommend using Lodash's _.round() function: https://lodash.com/docs/4.17.15#round
_.round(130.795, 2);
// 130.8