【问题标题】:How to limit the rounding of a Float Number to only its “Decimal Part” without affecting its “Whole Part”如何将浮点数的舍入限制为仅其“小数部分”而不影响其“整个部分”
【发布时间】:2020-10-30 03:39:04
【问题描述】:

我在 stackoverflow 上找不到任何询问或回答此问题的帖子。

正常的舍入方法将“浮点数”作为一个整体进行舍入(即它的小数部分和整数部分都在舍入过程中进行处理和影响)。 p>

所以,通常情况下(四舍五入):

   12.9768 Rounded to 3 decimal places is 12.977
           Rounded to 2 decimal places is 12.98
           Rounded to 1 decimal place  is 13.0     <== Whole part also changed
           Rounded to 0 decimal place  is 13       <== Whole part also changed

在上面的例子中,一旦小数部分达到整数,整个部分也会受到影响。

这对于几乎所有情况都很好,也很方便,当然这也是任何标准数字舍入方法的目的。

但是,我正在寻找的是仅对数字的小数部分(到指定的位数)进行四舍五入(使用javascript),但不影响整个部分number,所以(上面的例子会变成):

   12.9768 Rounded to 3 decimal places is 12.977
           Rounded to 2 decimal places is 12.98
           Rounded to 1 decimal place  is 12.9
           Rounded to 0 decimal place  is 12
           Rounded to 7 decimal places is 12.9768000

在上面,小数部分将四舍五入到任何所需的小数位但不会触及数字的整个部分

尾随零是必需的,因此输出格式将为字符串类型。

此过程将舍入限制为浮点数的小数部分,并带有限制上限/限制,因为舍入不会扩展到整个部分;即最大分数将始终为 0.999 等。

使用这种方法的一种情况是,在商店中,价格标签需要显示为 USD NN.mm,但无论会计系统在计算过程中做什么,它都无法创建一个整数。因此,如果原始购买价格为 22.45 美元,并且由于任何计算而进行的四舍五入一定不会导致 22 美元变为 23。因此,它可以是 22.99 以内的任何值。这是一个小数部分为 2 位小数(即美分)的示例,但如果小数部分不是 2,则需要一个通用且灵活的解决方案来仅舍入小数部分而不触及整个部分。

谢谢。

【问题讨论】:

    标签: javascript floating-point numbers rounding precision


    【解决方案1】:

    试试下面的函数……它基本上是把指定小数位后的所有内容都删掉了。

    function precission(n, count) {
      var indicator = Math.pow(10, count) || 1;
    
      return ((n * indicator) | 0) / indicator;
    }
    

    如果你想要尾随零,只需使用 string.padEnd(count, "0")

    更新:

    var num = 12.9768;
    
    function precission(n, count) {
      var indicator = Math.pow(10, count) || 1;
      var whole = n | 0;
      var decimal = n - whole;
      var rounded = Math.round(decimal * indicator) / indicator;
    
      return rounded >= 1 ? whole : whole + rounded;
    }
    
    console.log(precission(num, 0));
    console.log(precission(num, 1)); //prints 12 because otherwise it would have been 13
    console.log(precission(num, 2));
    console.log(precission(num, 3));
    console.log(precission(num, 6));

    这是你要找的吗?

    【讨论】:

    • 谢谢汤姆。一个问题是它没有正确舍入。例如precission(1.987,2)); 给出1.98 它应该是1.99。该功能应正常运行,但不涉及整个部分。
    • 这似乎比我想象的要复杂
    • 我想我只是误解了一些东西。您希望按照惯例对数字进行四舍五入,但如果您将四舍五入的数字四舍五入,它应该像原来的数字一样工作吗?我的方法只是在某个位置后去掉每个小数,这就是我认为你想要的。也许您需要将原始号码存储在某处以解决您的问题。我希望我是对的,否则我不确定问题到底是什么。
    • 它应该只对小数部分进行正常的四舍五入,但不能让四舍五入超过并改变整数。即整个部分必须保持完整。小数部分必须照常四舍五入到所需的小数位。
    【解决方案2】:

    按原样获取整数

     Math.floor(12.9768)
    

    它将为您提供您期望的整数,对于小数部分获取原样,或者您可以这样做

    Math.floor(12.9768) + ( 12.9768 - Math.floor(12.9768) )
    

    【讨论】:

    • 当数字为负数时,这会起作用吗?也许Math.trunc()
    【解决方案3】:

    没有一点javascript经验,我会尝试一个伪代码/javascript解决方案:

    function MA_Round(n, precision) {
      // break into whole and fractional parts
      var whole =  Math.trunc(n);
      var frac =  n - whole;
    
      // Round fraction
      var pow10 = Math.pow(10, precision);
      var rvalue = Math.round(frac*pow10)/pow10;
    
      // Form limit of highest fractional value and apply
      var limit = 1.0 - 1.0/pow10;
      if (Math.abs(rvalue) > limit) rvalue = limit;
    
      // Form result
      return whole + rvalue;
    }
    

    【讨论】:

    • 是的。这给了我一个思考的想法。谢谢大佬。
    • 由于输出需要尾随零(即无论如何都需要字符串输出),因此可能从一开始就将整数作为字符串处理。
    • @MohsenAlyafei 最后一部分whole + rvalue 可能会导致四舍五入,所以最好分别返回这两个值;打印整个部分,然后打印rvalue 部分。
    • @MohsenAlyafei 为了避免将 FP 值转换为 字符串 的舍入问题,这本身会导致舍入,请务必打印到带有 at 的字符串至少 17 个,也许是 18 个有效位。请务必尝试使用 FP 值小于 1.0 的任何代码,例如 0.999999999999999
    【解决方案4】:

    这个流程图可能是解决它的一种方法

    【讨论】:

      猜你喜欢
      • 2022-08-10
      • 2020-05-18
      • 2021-10-09
      • 1970-01-01
      • 1970-01-01
      • 2022-01-08
      • 2020-09-18
      • 2011-02-27
      • 2018-06-24
      相关资源
      最近更新 更多