Unix中的Roundup函数

时间:2016-05-25 09:16:45

标签: unix awk

我的要求如下

121.36
121.025
121.1
121.000

期望的输出

122
122
122
121

使用的命令

awk -F"." '{if($8>0){print $11}}'

3 个答案:

答案 0 :(得分:5)

您要求的是ceil()(用于“ceiling”)功能。当你正在寻找任何类型的舍入函数时,在你的例子中包含零和负数是很重要的,因为很容易弄错它所以使用这个输入文件:

$ cat file
1.999999
1.0
0.000001
0
-0.000001
-1.0
-1.999999

我们可以测试ceil()函数:

$ awk 'function ceil(x, y){y=int(x); return(x>y?y+1:y)} {print $0,ceil($0)}' file
1.999999 2
1.0 1
0.000001 1
0 0
-0.000001 0
-1.0 -1
-1.999999 -1

和相反的floor()函数:

$ awk 'function floor(x, y){y=int(x); return(x<y?y-1:y)} {print $0,floor($0)}' file
1.999999 1
1.0 1
0.000001 0
0 0
-0.000001 -1
-1.0 -1
-1.999999 -2

上述工作原因是int()截断为零(来自GNU awk手册):

int(x)
    Return the nearest integer to x, located between x and zero and
    truncated toward zero. For example, int(3) is 3, int(3.9) is 3,
    int(-3.9) is -3, and int(-3) is -3 as well.

所以负数的int()已经完成了你想要的天花板功能,即向上舍入,如果int()向下舍入正数,你只需要在结果中加1。 / p>

我在示例中使用了0.000001等,以避免人们误报测试添加一些数字的解决方案,例如0.9然后int()

另请注意,ceil()可缩写为:

function ceil(x){return int(x)+(x>int(x))}

但我为了清楚起见(如果x>int(x)的结果不是很明显/很明显,int()的结果是1或0)和效率(仅调用/Test/customer/edit/2一次而不是两次),我就这样写了。

答案 1 :(得分:1)

我试图在普通的bash中找到一种方法,但是由于bash只能进行整数运算,所以我失败了。你需要另一种语言来与你合作。

我会写一个shell函数作为其他langugage的包装器。例如:

templates/components/common/forms.html
templates/components/common/icons.html

输出

<%@ page isELIgnored="false" %>

任何其他语言都可以:$ ceil() { perl -MPOSIX=ceil -lpe '$_ = ceil($_)'; } $ ceil <<END 121.36 121.025 121.1 121.000 0.1 0 -0.1 -3.0 -3.1 END

答案 2 :(得分:0)

或者,不使用条件,

function ceil(x) { return int(x + (1 - 1e-15)); }

此处的性能差异可以忽略不计,但对于不存在的情况,我喜欢牢记这种方法。

151e-15 的选择源于具有 16 个有效数字的双精度浮点数,因此我们添加了带有 16 个 9 的 0.99...。这样 1 不会到达 2,但带有 14 个零的 1.0...01 会被四舍五入。


测试代码

echo 3 18 | awk '
    function ceil_old(x, y){ y=int(x); return(x>y?y+1:y) } 
    function ceil(x) { return int(x + (1 - 1e-15)); }
    { 
        x = $1; 
        n = $2; 
        for (i=0; i<n; ++i) { 
            y = 10 ** -i;
            z = ceil(x+y);
            w = ceil_old(x+y);
            if (z != w) {
                print x" + 1e-"i " = " x+y " -> " z " <=> " w; 
                exit 1; 
            }
            z = ceil(x-y); 
            w = ceil_old(x-y);
            if (z != w) {
                print x" - 1e-"i " = " x-y " -> " z " <=> " w;
                exit 1;
            }
        }
    }
'

1e-15 更改为 1e-161e-10 以查看这如何影响行为。