Awk尽管使用%e格式未输出科学计数法。

huangapple go评论52阅读模式
英文:

Awk not outputting in scientific notation despite %e

问题

我使用awk进行一些基本计算,并希望强制输出科学计数法。我使用OFMT="%.15e"来实现这一点。在大多数机器上,我得到了预期的输出:

$ awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'
4.483923595133619e+26

但是我的集群上的awk版本却显示:

$ awk --version | head --lines=2
GNU Awk 4.0.2
Copyright (C) 1989, 1991-2012 Free Software Foundation.

$ awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'
448392359513361882871234560

为什么这个版本/配置的awk没有按要求输出科学计数法?如何能够以可移植的方式获得我想要的结果(4.483923595133619e+26)?

英文:

I am using awk for some basic calculations and want to force my output to be in scientific notation. I am using OFMT="%.15e" to accomplish this. On most machines, I get the expected output:

$ awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'
4.483923595133619e+26

But a version of awk on my cluster gives:

$ awk --version | head --lines=2
GNU Awk 4.0.2
Copyright (C) 1989, 1991-2012 Free Software Foundation.

$ awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'
448392359513361882871234560

Why is this version/configuration of awk not outputting to scientific notation as requested? How can I portably get my desired result (4.483923595133619e+26
)?

答案1

得分: 4

Here's the translated content:

<strike>我认为您发现了GNU awk中的一个长期存在的错误。</strike>

GNU awk的行为是正确的。

这里是[POSIX所说的内容](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html):

> 具有与整数值完全相等的数值将通过等效于使用字符串`"%d"`作为`fmt`参数以及将要转换的数值作为第一个唯一的`expr`参数的`sprintf`函数(请参阅String Functions)来转换为字符串。

使用`printf`而不是设置`OFMT`不是解决gawk错误的方法。这是解决您的代码中的错误的方法。

任何足够大的浮点值都与整数完全相等。

(awk通过它们的值来区分整数和非整数的方式可能会让人感到困惑,如果您习惯了具有明确整数和浮点类型的语言。)

这里是发生的示例:

```bash
$ cat foo.awk
#!/usr/bin/awk -f

BEGIN {
    OFMT="%.16e"
    for (i = 50; i <= 55; i ++) {
        x = 2 ** i - 0.5
        printf("2**%d - 0.5 = %.3f = ", i, x)
        print(x)
    }
}
$ ./foo.awk
2**50 - 0.5 = 1125899906842623.500 = 1.1258999068426235e+15
2**51 - 0.5 = 2251799813685247.500 = 2.2517998136852475e+15
2**52 - 0.5 = 4503599627370495.500 = 4.5035996273704955e+15
2**53 - 0.5 = 9007199254740992.000 = 9007199254740992
2**54 - 0.5 = 18014398509481984.000 = 18014398509481984
2**55 - 0.5 = 36028797018963968.000 = 36028797018963968
$

最初我认为这是gawk的错误,我在这里提交了一个错误报告:

https://lists.gnu.org/archive/html/bug-gawk/2023-05/msg00010.html

来自Andrew J. Schorr的回复正确地说明了这是预期行为。

https://lists.gnu.org/archive/html/bug-gawk/2023-05/msg00011.html

邮件列表上有更多的回复。文档可能没有充分解释OFMTCONVFMT之间的关系。我上面引用的POSIX措辞是在讨论CONVFMT

https://lists.gnu.org/archive/html/bug-gawk/2023-05/threads.html


请注意,我已根据您的要求省略了代码部分,并只提供了翻译的内容。

<details>
<summary>英文:</summary>

&lt;strike&gt;I believe you&#39;ve found a longstanding bug in GNU awk.&lt;/strike&gt;

GNU awk is behaving correctly.

Here&#39;s [what POSIX says](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html):

&gt; A numeric value that is exactly equal to the value of an integer (see Concepts Derived from the ISO C Standard) shall be converted to a string by the equivalent of a call to the `sprintf` function (see String Functions) with the string `&quot;%d&quot;` as the `fmt` argument and the numeric value being converted as the first and only `expr` argument.

Using `printf` rather than setting `OFMT` is not a workaround for a gawk bug. It&#39;s the solution to the bug in your code.

Any sufficiently large floating-point value is exactly equal to an integer.

(The way awk distinguishes between integers and non-integers by their values can be a bit confusing if you&#39;re accustomed to languages that have distinct integer and floating-point types.)

Here&#39;s a demonstration of what&#39;s happening:

$ cat foo.awk
#!/usr/bin/awk -f

BEGIN {
OFMT="%.16e"
for (i = 50; i <= 55; i ++) {
x = 2 ** i - 0.5
printf("2**%d - 0.5 = %.3f = ", i, x)
print(x)
}
}
$ ./foo.awk
250 - 0.5 = 1125899906842623.500 = 1.1258999068426235e+15
2
51 - 0.5 = 2251799813685247.500 = 2.2517998136852475e+15
252 - 0.5 = 4503599627370495.500 = 4.5035996273704955e+15
2
53 - 0.5 = 9007199254740992.000 = 9007199254740992
254 - 0.5 = 18014398509481984.000 = 18014398509481984
2
55 - 0.5 = 36028797018963968.000 = 36028797018963968
$


I initially thought this was a bug in gawk, and I submitted a bug report here:

https://lists.gnu.org/archive/html/bug-gawk/2023-05/msg00010.html

A reply from Andrew J. Schorr correctly says that this is the expected behavior.

https://lists.gnu.org/archive/html/bug-gawk/2023-05/msg00011.html

There have been more responses on the mailing list. The documentation is probably insufficiently clear about the relationship between `OFMT` and `CONVFMT`. The POSIX wording I cited above is talking about `CONVFMT`.

https://lists.gnu.org/archive/html/bug-gawk/2023-05/threads.html

</details>



# 答案2
**得分**: 1

I did run

awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'


using **gawk 4.2.1** and it did give

448392359513361882871234560


I was unable to find reason for that, but determined that using [`printf`][1] does what you want, that is

awk 'BEGIN { printf("%.15e\n", 4.483923595133619e+29 / 1000) }'


using **gawk 4.2.1** did give

4.483923595133619e+26


Observe need to apply line terminator yourself (`\n` means newline). Please try it with your `awk` and write if it does work as intended.

[1]: https://www.gnu.org/software/gawk/manual/html_node/Printf-Examples.html

<details>
<summary>英文:</summary>

I did run

    awk &#39;BEGIN { OFMT = &quot;%.15e&quot;; print 4.483923595133619e+29 / 1000 }&#39;

using **gawk 4.2.1** and it did give

    448392359513361882871234560

I was unable to find reason for that, but determined that using [`printf`][1] does what you want, that is

    awk &#39;BEGIN { printf(&quot;%.15e\n&quot;, 4.483923595133619e+29 / 1000) }&#39;

using **gawk 4.2.1** did give

    4.483923595133619e+26

Observe need to apply line terminator yourself (`\n` means newline). Please try it with your `awk` and write if it does work as intended.

  [1]: https://www.gnu.org/software/gawk/manual/html_node/Printf-Examples.html

</details>



huangapple
  • 本文由 发表于 2023年5月6日 15:44:13
  • 转载请务必保留本文链接:https://go.coder-hub.com/76187717.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定