2

在 mawk 中除以零时,我得到六个不同的结果:

$ echo | awk '{print -1/0 }' ; echo $?
-inf
0
$ echo | awk '{print 0/0 }' ; echo $?
-nan
0
$ echo | awk '{print 1/0 }' ; echo $?
inf
0
$ echo | awk '{printf ("%i\n", -1/0) }' ; echo $?
-2147483647
0
$ echo | awk '{printf ("%i\n", 0/0) }' ; echo $?
-2147483647
0
$ echo | awk '{printf ("%i\n", 1/0) }' ; echo $?
2147483647
0

我得到每个案例的“成功”退出代码。

  1. 为什么会这样?
  2. 我能做些什么呢?在进行除法之前,我是否总是需要检查零除数,或者有什么方法可以依赖 awk 的错误处理和退出代码?
4

3 回答 3

6

我猜你正在使用, mawknone of或有这种行为,不支持除以零。awknawkgawk

您的答案是+inf正无穷大,nan“不是数字”和-inf负无穷大,一切都符合预期。这些仅在打印float时输出,即%.6g默认值OFMT(用于打印数字的默认格式)。

$ mawk 'BEGIN {printf ("%i\n", 1/0) }'
2147483647
$ mawk 'BEGIN {printf ("%f\n", 1/0) }'
inf
$ gawk 'BEGIN {printf ("%f\n", 1/0) }'
gawk: fatal: division by zero attempted

当您使用“%i”显式打印时,您会得到 +HUGE 或 -HUGE,这将转换为 int(在您的情况下为带符号的 32 位)并打印为 + 或 - (2^31-1)。

通常的做法是始终检查除以零,理想情况下,通过重新组织表达式来最小化您需要检查的次数——除以零会导致 awk 的其他实现简单地终止。

何时mawk构建它会检测您的 C 数学库的功能:

$ ./configure
[...]
checking handling of floating point exceptions
    division by zero does not generate an exception
    overflow does not generate an exception
    math library supports ieee754

NOINFO_SIGFPE如果您使用以下定义构建,您可以获得“标准”行为:

$ ./configure CFLAGS="-DNOINFO_SIGFPE"
$ make clean && make
$ ./mawk 'BEGIN {printf ("%f\n", 1/0) }'
mawk: run time error: division by zero
    FILENAME="" FNR=0 NR=0

(虽然这没有记录,但它可能不是你应该依赖的东西)。

于 2013-01-29T12:30:18.233 回答
3

在尝试了不同的 AWK“方言”之后,我得出了以下结论:

尝试awk

echo | awk '{print -1/0 }' ; echo $?

我正进入(状态:

awk: (FILENAME=- FNR=1) fatal: division by zero attempted
2

尝试gawk

echo | gawk '{print -1/0 }' ; echo $?

我正进入(状态:

gawk: (FILENAME=- FNR=1) fatal: division by zero attempted
2

尝试mawk

echo | mawk '{print -1/0 }' ; echo $?

我正进入(状态:

-inf
0

awk --version如果我是您,我会尝试识别您的“默认方言” gawk

PS:我正在运行 Ubuntu 11.10。

PS:在我的情况下awkgawk.

于 2013-01-29T11:55:57.957 回答
0

甚至 gnu gawk 根据调用标志表现出不同行为的组合并不难:

(这些测试也更简单,因为输出基于调用 awk/start-up 选项的行为,而不是可以手动覆盖的参数常量。

我自己使用的 gawk 符号(GMP/MPFR 是不言自明的)-

E = -e aka standard call
S = -S `—-sandbox`
P = -P `--posix`
c = -c `—-traditional`
n = -n `--non-decimal-data`
    #  (-nan):x:gawk-S/c/E/mpfr
    #  (+inf):x:gawk-n/P
    #  (+nan):x:gawk-GMP/GMP+mpfr
    #   ( 0 ):x:nawk
    #   (inf):x:mawk
    #   (nan):x:mawk2

      x = -log((log(0)*log(0))^-log(-0))/(-"0xABCD")^-!-"";

    # (+nan) :gawk-GMP/MPFR
    #        (NaN:mpfr_log())
    #  (nan) :nawk/mawk/mawk2
    # (-nan) :gawk-E/P/c

        x = log(log((-log(0))/-log(0)));

    # (-inf):nawk
    #  (inf):mawk/mawk2
    # (+inf):gawk-ALL

        y = log(log((-log(0))^-log(0)));

    # (-inf):gawk-GMP
    # (-inf):nawk
    # (-nan):gawk-P/E/c
    #  (nan):mawk/mawk2

        z = log(-log(1))-(-"")^-!-"";

    # (+nan):gawk-GMP
    #  (inf):mawk/mawk2
    #  (nan):nawk
    # (+inf):gawk-except-GMP

        z = log(-log(0))-(-"")^-!-"";

    # (-inf):nawk/gawk-GMP
    #  (inf):mawk/mawk2
    # (+inf):gawk-except-GMP

        z = -(-"")^-!-"";

    #  (inf):nawk
    #  ( 0 ):gawk-GMP
    # (-inf):all others

        xn = (-"")^-!"";

这些例子可能不只是被零除,但它确实强调了在边缘情况下,它们的行为变化很大。这是一个整理表,以便更容易理解:

    a = log(log((-log(0))^-log(0)));
    b = log(log((-log(0))/-log(0)));;
    c = -log((log(0)*log(0))^-log(-0))/(-"0xABCD")^-!-"";
    d = log(-log(0))-(-"")^-!-"";
    e = log(-log(1))-(-"")^-!-"";

/usr/local/bin/nawk  ::  -inf ::  nan ::   0  ::  nan :: -inf ::
---------------------------------------------------------------
/usr/local/bin/mawk  ::   inf ::  nan ::  inf ::  inf ::  nan ::
---------------------------------------------------------------
/usr/local/bin/mawk2 ::   inf ::  nan ::  nan ::  inf ::  nan ::
---------------------------------------------------------------
/usr/local/bin/gawk -e:: +inf :: -nan :: -nan :: +inf :: -nan ::
/usr/...,/gawk -l mpfr:: +inf :: -nan :: -nan :: +inf :: -nan ::
/usr/local/bin/gawk -S:: +inf :: -nan :: -nan :: +inf :: -nan ::
/usr/local/bin/gawk -c:: +inf :: -nan :: -nan :: +inf :: -nan ::
---------------------------------------------------------------
/usr/local/bin/gawk -P:: +inf :: -nan :: +inf :: +inf :: -nan ::
/usr/local/bin/gawk -n:: +inf :: -nan :: +inf :: +inf :: -nan ::
----------------------------------------------------------------
/usr/local/bin/gawk -M:: +inf :: +nan :: +nan :: +nan :: -inf ::
----------------------------------------------------------------
于 2021-10-09T11:44:21.893 回答