私が持ちたいのは、Number.prototype.toPrecision()のほぼ反対です。つまり、数値がある場合、小数点以下の桁数はいくつですか?例えば。
(12.3456).getDecimals() // 4
(文字列に変換せずに)これをより高速に行う方法を知りたい人のために、ここに解決策があります:
function precision(a) {
var e = 1;
while (Math.round(a * e) / e !== a) e *= 10;
return Math.log(e) / Math.LN10;
}
編集:Edgeケースをカバーしたより完全なソリューション:
function precision(a) {
if (!isFinite(a)) return 0;
var e = 1, p = 0;
while (Math.round(a * e) / e !== a) { e *= 10; p++; }
return p;
}
1つの可能な解決策(アプリケーションによって異なります):
var precision = (12.3456 + "").split(".")[1].length;
「精度」で「小数点以下の桁数」を意味する場合、 浮動小数点数はバイナリ であるため、それは不可能です。小数点以下の桁数はない。小数点以下の桁数が少ないほとんどの値には、バイナリの繰り返し桁があり、逆に変換された場合必ずしも元の10進数が得られるとは限りません。
フロートの「小数点以下の桁数」で機能するコードは、一部の数値で予期しない結果を生じる可能性があります。
@boolean_Typeの指数処理方法に基づきますが、正規表現は避けます:
function getPrecision (value) {
if (!isFinite(value)) { return 0; }
const [int, float = ''] = Number(value).toFixed(12).split('.');
let precision = float.length;
while (float[precision - 1] === '0' && precision >= 0) precision--;
return precision;
}
以下を試してください
function countDecimalPlaces(number) {
var str = "" + number;
var index = str.indexOf('.');
if (index >= 0) {
return str.length - index - 1;
} else {
return 0;
}
}
小数の数を決定するネイティブ関数はありません。できることは、数値を文字列に変換してから、10進数の区切り文字.
:
Number.prototype.getPrecision = function() {
var s = this + "",
d = s.indexOf('.') + 1;
return !d ? 0 : s.length - d;
};
(123).getPrecision() === 0;
(123.0).getPrecision() === 0;
(123.12345).getPrecision() === 5;
(1e3).getPrecision() === 0;
(1e-3).getPrecision() === 3;
しかし、あなたをだますのはフロートの性質です。 1
は、0.00000000989
か何か。上記が実際のアプリケーションで実際にどれだけうまく機能するかはわかりません。
@ blackpla9ueコメントに基づいて、数値の指数形式を考慮します。
function getPrecision (num) {
var numAsStr = num.toFixed(10); //number can be presented in exponential format, avoid it
numAsStr = numAsStr.replace(/0+$/g, '');
var precision = String(numAsStr).replace('.', '').length - num.toFixed().length;
return precision;
}
getPrecision(12.3456); //4
getPrecision(120.30003300000); //6, trailing zeros are truncated
getPrecision(15); //0
getPrecision(120.000)) //0
getPrecision(0.0000005); //7
getPrecision(-0.01)) //2
番号が有効であると仮定します。
let number = 0.999;
let noOfPlaces = number.includes(".") //includes or contains
? number.toString().split(".").pop().length
: 0;
以下に、ライブラリを使用する例( BigNumber.js )とライブラリを使用しない例の2つを示します。特定の入力番号(inputNumber
)の小数点以下の桁数が、小数点以下の最大桁数(tokenDecimals
)以下であることを確認するとします。
BigNumber.jsを使用
import BigNumber from 'bignumber.js'; // ES6
// const BigNumber = require('bignumber.js').default; // CommonJS
const tokenDecimals = 18;
const inputNumber = 0.000000000000000001;
// Convert to BigNumber
const inputNumberBn = new BigNumber(inputNumber);
// BigNumber.js API Docs: http://mikemcl.github.io/bignumber.js/#dp
console.log(`Invalid?: ${inputNumberBn.dp() > tokenDecimals}`);
BigNumber.jsなし
function getPrecision(numberAsString) {
var n = numberAsString.toString().split('.');
return n.length > 1
? n[1].length
: 0;
}
const tokenDecimals = 18;
const inputNumber = 0.000000000000000001;
// Conversion of number to string returns scientific conversion
// So obtain the decimal places from the scientific notation value
const inputNumberDecimalPlaces = inputNumber.toString().split('-')[1];
// Use `toFixed` to convert the number to a string without it being
// in scientific notation and with the correct number decimal places
const inputNumberAsString = inputNumber.toFixed(inputNumberDecimalPlaces);
// Check if inputNumber is invalid due to having more decimal places
// than the permitted decimal places of the token
console.log(`Invalid?: ${getPrecision(inputNumberAsString) > tokenDecimals}`);
次のアプローチは機能しますか?
var num = 12.3456
console.log(num - Math.floor(num))
または
console.log(num - parseInt(num))