【问题标题】:Get decimal portion of a number with JavaScript使用 JavaScript 获取数字的小数部分
【发布时间】:2010-12-22 18:20:08
【问题描述】:

我有浮点数,例如 3.21.6

我需要将数字分成整数和小数部分。例如,3.2 的值将被拆分为两个数字,即 30.2

获取整数部分很容易:

n = Math.floor(n);

但我无法获取小数部分。 我试过这个:

remainder = n % 2; //obtem a parte decimal do rating

但它并不总是正常工作。

前面的代码有如下输出:

n = 3.1 // gives remainder = 1.1

我在这里缺少什么?

【问题讨论】:

  • 请注意,n = Math.floor(n); 仅返回您想要的非负数结果(整数部分)
  • 简化使用% 1 而不是% 2
  • decimalPart = number - Math.floor(number) 进一步,您可以为其添加精度。 parseFloat(decimalPart.toPrecision(3)) // 精确到 3 位的浮点数

标签: javascript floating-point numbers decimal rounding


【解决方案1】:

使用1,而不是2

js> 2.3 % 1
0.2999999999999998

【讨论】:

  • 在 0.2999999999999998 等于 0.3 的世界中,这可能是可以接受的。对我来说不是......因此,为了解决这个挑战,我会避免使用 Math.*% 操作。
  • 为避免指出的浮点舍入问题,在某些情况下使用 toFixed 可能会有所帮助,例如(2.3 % 1).toFixed(4) == "0.3000".
  • (2.3 % 1).toFixed(4).substring(2) = "3000" 如果你需要它而不需要0.
  • 在一个出现了2.3 而不是23 的世界里,0.2999999999999998 是完全可以接受的,尽管它看起来对人眼有多么侮辱。
  • @GershomMaes 在很多情况下这个数字是不可接受的。
【解决方案2】:
var decimal = n - Math.floor(n)

虽然这不适用于负数,但我们可能不得不这样做

n = Math.abs(n); // Change to positive
var decimal = n - Math.floor(n)

【讨论】:

  • 如果您已经有了整数部分,则无需再次调用Math.floor() -- 只需使用您计算的整数部分即可。
  • var n = 3.2, integr = Math.floor(n), decimal = n - integr; 只使用一次 Math.floor()integr = 3; decimal = 0.20000000000000018;
  • 为了使用负数,只需将Math.floor 替换为Math.trunc
  • 这返回了一个不准确的数字,就像我期望从 100.80 得到 0.80,而不是 0.79999...我通过添加 decimal.toFixed(2) 解决了这个问题
【解决方案3】:

你可以转换成字符串,对吧?

n = (n + "").split(".");

【讨论】:

  • 这在任何地方都可以正常工作,除了欧洲大陆,逗号是小数点分隔符。如果您打算使用此解决方案,如果您是跨国公司并以欧洲为目标,请记住考虑到这一点,因为此解决方案对他们来说效果不佳。
  • 我来自欧洲大陆,使用的是法国 Firefox,它可以工作。通常我们会在法国使用逗号作为小数分隔符。原因是在 JavaScript 中,将数字转换为字符串时不涉及文化,尽管我更喜欢使用 n.toString() 而不是 n + "",因为它更具可读性。
  • 如果速度很关键,那么n + "" 确实更好(参见jsperf.com/number-vs-number-tostring-vs-string-number
  • @cdmdotnet JS 使用. 作为小数点分隔符,因此如果输入变量的类型是浮点数,则在任何地方都可以。如果您的输入是字符串,您只需要处理该问题。我还必须注意,这个答案会返回一个数组中的字符串。更完整的解决方案是parseFloat('0.' + (n + '').split('.')[1])
  • @cdmdotnet 位置无关解决方案在这里:stackoverflow.com/a/59469716/1742529
【解决方案4】:

0.2999999999999998 是一个可接受的答案吗?如果我是提问者,我希望得到 0.3 的答案。我们这里有错误精度,我对 floor、% 等的实验表明 Javascript 喜欢这些操作的错误精度。所以我认为使用转换为字符串的答案是正确的。

我会这样做:

var decPart = (n+"").split(".")[1];

具体来说,我使用的是 100233.1,我想要答案“.1”。

【讨论】:

  • 我大体上同意,但你不能依赖 '.'正则表达式为the decimal separator is an i18n character
  • @jomofrodo 实际上,有些人可能想要非四舍五入的值。我不记得 OP 要求一个四舍五入的值,只是拆分值。
  • @VVV 是的,有些人可能想要非四舍五入的值。但仅仅因为您可能想要精确到小数点后 9 位并不意味着您的输入数据实际上支持它。这就是为什么它被称为“错误精度”。如果您的输入是 3.1,那么您的答案可以具有的最精确度是十分之一,即 0.1。如果您回答 0.09,则意味着您实际上已经计算/测量到了 100 分之一的精度,而实际上原始输入只精确到了 10 分之一的精度。
  • @MarcelStör 可以轻松处理:var decPart = (n.toLocaleString("en")).split(".")[1];
  • .toString() 不考虑 i18n。小数分隔符将始终为 . according to MDNthe ECMA spec
【解决方案5】:

这是我的做法,我认为这是最直接的做法:

var x = 3.2;
int_part = Math.trunc(x); // returns 3
float_part = Number((x-int_part).toFixed(2)); // return 0.2

【讨论】:

    【解决方案6】:

    一个简单的方法是:

    var x = 3.2;
    var decimals = x - Math.floor(x);
    console.log(decimals); //Returns 0.20000000000000018

    不幸的是,这并没有返回确切的值。但是,这很容易解决:

    var x = 3.2;
    var decimals = x - Math.floor(x);
    console.log(decimals.toFixed(1)); //Returns 0.2

    不知道小数位数的可以用这个:

    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

    【讨论】:

      【解决方案7】:

      语言独立方式:

      var a = 3.2;
      var fract = a * 10 % 10 /10; //0.2
      var integr = a - fract; //3
      

      请注意,它仅适用于具有一个分数长度的数字)

      【讨论】:

      • 您能解释一下为什么您认为这是与语言无关的吗?它是 JavaScript。
      • @hotzst,没有特定语言的功能
      • 语言独立,因为它只是纯粹的数学。实用的解决方案。具有所需的分数长度:var factor = Math.pow(10, desiredFractionLength); var fract = a * factor % factor / factor;
      【解决方案8】:

      你可以使用parseInt()函数来获取整数部分而不是使用它来提取小数部分

      var myNumber = 3.2;
      var integerPart = parseInt(myNumber);
      var decimalPart = myNumber - integerPart;
      

      或者你可以使用正则表达式:

      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]}`)
             }
         }
      }
      

      【讨论】:

      • decimalPart 即将到来 0.20000000000000018 ...这真的很难做到,因为 0.2 < 0.20000000000000018 返回 true.. 3.2 应该返回 0.2 :P 造成如此多的违规行为并使用 .toFixed(2) 返回字符串:P
      • @HimanshuBansal 那是JavaScript problem(与stackeoverflow question 类似)。你可以使用我建议的第二种方法。
      • 嗯,我有一点不同的问题陈述......有点用你的两种方法:P来解决它.. ^^
      【解决方案9】:

      无论小数点分隔符的区域设置如何,以下操作都有效...条件是仅使用一个字符作为分隔符。

      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);
      

      它不漂亮,但它很准确。

      【讨论】:

      • 那当然是一个字符串,所以如果你想要它作为一个数字,你可能需要先 parseInt() 。你不应该需要 parseFloat()... 除非我在这里缺少一些以 8 为底的数字而不是以 10 为底的数字...我从几年前模糊地记得的东西
      【解决方案10】:

      如果精度很重要并且您需要一致的结果,这里有一些命题会将任何数字的小数部分作为字符串返回,包括前导的“0.”。如果您需要它作为浮点数,只需在最后添加var f = parseFloat( result )

      如果小数部分为零,则返回“0.0”。未测试 Null、NaN 和未定义的数字。

      1。字符串.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");
      

      这是一个 jsPerf 链接:https://jsperf.com/decpart-of-number/

      我们可以看到命题 #2 是最快的。

      【讨论】:

      • 不要使用这些。一旦数字渲染切换到工程,它们就会中断。它们也不区分区域设置。
      • 你能解释一下“数字渲染切换到工程”吗?此外,本地化也不相关,因为我们只需要数字的小数部分,而不是表示数字的本地化字符串。
      【解决方案11】:

      一个不错的选择是将数字转换成字符串,然后拆分。

      // 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
      

      一行代码

      let [firstNumber, secondNumber] = [+number.toString().split('.')[0], +number.toString().split('.')[1]];
      

      【讨论】:

        【解决方案12】:

        取决于您之后的使用情况,但这个简单的解决方案也可以帮助您。

        我并不是说它是一个好的解决方案,但对于一些具体的案例来说是可行的

        var a = 10.2
        var c = a.toString().split(".")
        console.log(c[1] == 2) //True
        console.log(c[1] === 2)  //False
        

        但这将比@Brian M. Hunt 提出的解决方案花费更长的时间

        (2.3 % 1).toFixed(4)
        

        【讨论】:

        • 这在任何地方都可以正常工作,除了欧洲大陆,逗号是小数点分隔符。如果您打算使用此解决方案,如果您是跨国公司并以欧洲为目标,请记住考虑到这一点,因为此解决方案对他们来说效果不佳。
        【解决方案13】:

        我正在使用:

        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]);
        }
        

        输入:-556.123444444

        结果:123444444

        【讨论】:

          【解决方案14】:

          您可以将其转换为字符串并使用replace 方法将整数部分替换为零,然后将结果转换回数字:

          var number = 123.123812,
              decimals = +number.toString().replace(/^[^\.]+/,'0');
          

          【讨论】:

          • 这个解决方案在逗号是小数点分隔符的欧洲大陆不起作用吗??
          • @preston 您可以将正则表达式中的点替换为您喜欢的任何其他分隔符(例如/^[^,]/),但您应该将结果保留为字符串(删除+ 运算符) 以避免NaN 结果。
          • 这不是它的工作原理,使他们的代码通用或被视为失败。
          • 我认为你的意思是注定要连枷
          【解决方案15】:

          数学函数更快,但总是返回非本机预期值。 我发现最简单的方法是

          (3.2+'').replace(/^[-\d]+\./, '')
          

          【讨论】:

            【解决方案16】:

            避免数学不精确的最佳方法是转换为字符串,但使用 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))

            【讨论】:

              【解决方案17】:

              我有一个案例,我知道所有有问题的数字都只有一个小数,并且想将小数部分作为整数,所以我最终使用了这种方法:

              var number = 3.1,
                  decimalAsInt = Math.round((number - parseInt(number)) * 10); // returns 1
              

              这也适用于整数,在这些情况下返回 0。

              【讨论】:

                【解决方案18】:
                n = Math.floor(x);
                remainder = x % 1;
                

                【讨论】:

                • 不适用于“3.02”,第一个小数位为零!我发布了一个具有高效功能的答案,您可以测试一下吗?
                【解决方案19】:

                我喜欢这个答案https://stackoverflow.com/a/4512317/1818723 只需要应用浮点修复

                function fpFix(n) {
                  return Math.round(n * 100000000) / 100000000;
                }
                
                let decimalPart = 2.3 % 1; //0.2999999999999998
                let correct = fpFix(decimalPart); //0.3
                

                功能齐全处理正反两面

                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
                

                附:如果您是加密货币交易平台开发人员或银行系统开发人员或任何 JS 开发人员;)请在任何地方申请 fpFix。谢谢!

                【讨论】:

                  【解决方案20】:

                  2021 年更新

                  处理精度(或不处理)的优化版本。

                  // 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

                  【讨论】:

                    【解决方案21】:

                    您可以简单地使用parseInt() 函数来提供帮助,例如:

                    let decimal = 3.2;
                    let remainder = decimal - parseInt(decimal);
                    document.write(remainder);

                    【讨论】:

                      【解决方案22】:

                      在看了其中几个之后,我现在正在使用...

                      var rtnValue = Number(7.23);
                      var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);
                      

                      【讨论】:

                        【解决方案23】:

                        虽然我回答这个问题很晚,但请看一下代码。

                        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)
                        

                        【讨论】:

                        • 逗号用作小数点分隔符时会失败。
                        【解决方案24】:

                        浮点十进制符号和数字格式可以依赖于国家(.,),因此保留浮点部分的独立解决方案是:

                        getFloatDecimalPortion = function(x) {
                            x = Math.abs(parseFloat(x));
                            let n = parseInt(x);
                            return Number((x - n).toFixed(Math.abs((""+x).length - (""+n).length - 1)));
                        }
                        

                        ——它是国际化的解决方案,而不是依赖于位置:

                        getFloatDecimalPortion = x => parseFloat("0." + ((x + "").split(".")[1]));
                        

                        逐步解决方案描述:

                        1. parseFloat() 保证输入正确
                        2. Math.abs() 用于避免负数问题
                        3. n = parseInt(x) 获取小数部分
                        4. x - n 用于减去小数部分
                        5. 我们现在有零小数部分的数字,但 JavaScript 可以给我们额外的浮动部分数字,这是我们不想要的
                        6. 因此,通过调用toFixed() 来限制额外的数字,并在原始浮点数x 的浮动部分中使用位数。计数计算为原始数字 x 和数字 n 在其字符串表示形式中的长度之差。

                        【讨论】:

                          【解决方案25】:

                          此函数将浮点数拆分为整数并以数组形式返回:

                          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 ]

                          您可以将其扩展为仅返回现有数字和null(如果不存在数字):

                          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 ]

                          【讨论】:

                          • 不适用于“console.log(splitNumber(3.02));”,第一个小数位为零!
                          • 我发布了一个高效功能的答案,你能测试一下吗?
                          【解决方案26】:
                          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
                          

                          【讨论】:

                          • 这在我看来不像 javascript!
                          • 这不是java脚本
                          • 在 JS 中应该是这样的:var a = 3.2; var b = parseInt(a, 10); var c = a - b;
                          猜你喜欢
                          • 1970-01-01
                          • 1970-01-01
                          • 2023-03-12
                          • 2010-11-12
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          • 2012-10-13
                          • 2017-06-27
                          相关资源
                          最近更新 更多