【问题标题】:Rounding the result using dc (desk calculator)使用 dc(桌面计算器)对结果进行四舍五入
【发布时间】:2013-10-19 18:36:36
【问题描述】:

是否可以在 shell 脚本中使用 dc 对堆栈顶部进行舍入? 如果是,是否有命令将结果向上和向下舍入?

谢谢大家!

【问题讨论】:

    标签: rounding dc


    【解决方案1】:

    dc manual 说:

    大多数算术运算都受“精度值”的影响,您可以使用k 命令进行设置。默认精度值为零...

    / 弹出两个值,将第二个弹出的值与第一个弹出的值相除,然后推送结果。小数位数由精度值指定。

    因此,您可以使用0k1/ 或仅使用1/ 截断(向零舍入),如果您知道精度为 0(默认为 0)。例如:

    $ dc -e '12.9 1/ p'
    12
    $ dc -e '_12.9 1/ p'
    -12
    

    其他类型的舍入比较困难。要四舍五入到最接近的整数,您可以使用[_1*]sad.5r0>a+0k1/,例如:

    $ dc -e '12.9 [_1*]sad.5r0>a+0k1/ p'
    13
    $ dc -e '_12.9 [_1*]sad.5r0>a+0k1/ p'
    -13
    

    快速解释:

    1. [_1*]sa 将命令 _1*(乘以 -1)存储在寄存器 a 中。
    2. d 复制栈顶的值(我们要四舍五入的值,称为 v)。
    3. .5r 压入 0.5,然后交换顶部的两个值,因此堆栈现在是 v 0.5 v
    4. 如果 0 > v(即,如果 v 为负),0>a 执行寄存器 a 中的命令。如果 v 为正,则堆栈现在为 0.5 v,如果 v 为负,则为 -0.5 v。李>
    5. + 添加前两个值并推动 v + 0.5 如果 v 是正数,或 v - 0.5 如果 v em> 为负数。
    6. 0k1/ 如上所述截断。

    如果您知道要四舍五入的数字是非负数,您可以使用.5+0k1/;如果您还知道精度为 0,则可以使用 .5+1/

    向下取整,请使用[dX[1-]sa0<a]sad0>a0k1/

    四舍五入,请使用[dX[1+]sa0<a]sad0<a0k1/

    所有这些建议都使用寄存器a,因此您可能需要在实际程序中进行调整。

    【讨论】:

      【解决方案2】:

      在 Gareth 的回答的基础上,使用以下 银行家的四舍五入(即四舍五入到最接近的 偶数整数):[_1*]sa[d1r0>a+]sbd0k1/2%0!=b1/

      注意这使用了额外的寄存器,b

      这有点密集,所以让我们分解一下:

      [_1*]sa         #1- Assign a macro "$input *= -1" to register 'a'
      [d1r0>a+]sb     #2- Assign a macro "if($input<0){$input -= 1} else{$input += 1}"
                      #     to register 'b'
      d               #3- Duplicate the input value; the duplicate will be used 
                      #     to decide if the input is odd or even.
      0k              #4- Set precision to 0; this makes the 1/ operation truncate 
                      #     all digits to the right of the decimal point.
      1/              #5- Truncate those decimal places on our duplicate input.
      2%              #6- Modulo 2; if we get 0, it was even, otherwise it's odd.
                      #     Note this consumes the duplicate from line #3.
      0!=b            #7- If it was odd, run the macro in register 'b'. This adds +/-1
                      #     to the input, respectively if it's positive or negative.
      1/              #8- Truncate decimal places; if the input was odd we're now
                      #     at floor($input+1) for positive or floor($input-1)
                      #     for negative; if it was even we're at floor($input).
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-06-29
        • 2014-10-29
        • 2010-09-06
        • 2011-12-12
        • 1970-01-01
        • 1970-01-01
        • 2019-07-02
        相关资源
        最近更新 更多