2013-10-11 32 views

回答

6

dc manual說:

大多數運算是由「精確值」,您可以用k命令設置的影響。默認精度值爲零...

/彈出兩個值,將從彈出的第一個彈出的第二個值分開,並推送結果。小數位數由精度值指定。

所以你可以截斷使用0k1/,或只是1/如果你知道精度爲0,這是默認(向零)。例如:

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

其他類型的四捨五入更困難。註冊a

  1. [_1*]sa存儲命令_1*(乘以-1):爲輪最接近的整數,您可以使用[_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 
    

    的簡單說明。

  2. d重複堆棧頂部的值(我們想要的值,稱爲v)。
  3. .5r推0.5,然後交換前兩個值,所以堆棧現在是v 0.5 v
  4. 0>a寄存器執行命令a如果0>v(即,如果v是負的)。堆棧現在0.5 v如果v是正的,或-0.5 v如果v是負的。
  5. +增加頂部的兩個值並推動v + 0.5如果v是正的,或v - 0.5如果v是負的。
  6. 0k1/如上所述截斷。

如果您知道您舍入的數字是非負數,則可以使用.5+0k1/;如果您另外知道精度爲0,則可以使用.5+1/

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

取整,使用[dX[1+]sa0<a]sad0<a0k1/

所有這些建議都使用寄存器a,因此您可能需要在實際的程序中調整它們。

1

大廈加雷思的答案,請使用以下的銀行家舍入(即四捨五入到最接近甚至整數):[_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).