使用dc(桌面计算器)舍入结果

时间:2013-10-11 15:48:09

标签: rounding dc

是否可以在shell skript中使用 dc 围绕堆栈顶部? 如果是,是否有命令来上下舍入结果?

谢谢你们!

2 个答案:

答案 0 :(得分:7)

dc manual说:

  

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

     

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

因此,您可以使用0k1/ 截断(向零舍入),如果您知道精度为0,则可以仅1/,默认情况下为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>
  5. 0>a执行寄存器a中的命令 v (即,如果 v 为负数)。如果 v 为正,则堆栈现在为0.5 v ;如果 v 为负,则堆栈为-0.5 v
  6. +添加前两个值,如果 v 为正,则推送 v + 0.5,或 v - 如果< em> v 是否定的。
  7. 0k1/如上所述截断。
  8. 如果您知道要舍入的数字是非负数,则可以使用.5+0k1/;如果您还知道精度为0,则可以使用.5+1/

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

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

    所有这些建议都使用注册表a,因此您可能需要在实际程序中对其进行调整。

答案 1 :(得分:3)

根据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).