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

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

Awk not outputting in scientific notation despite %e

问题

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

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

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

  1. $ awk --version | head --lines=2
  2. GNU Awk 4.0.2
  3. Copyright (C) 1989, 1991-2012 Free Software Foundation.
  4. $ awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'
  5. 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:

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

But a version of awk on my cluster gives:

  1. $ awk --version | head --lines=2
  2. GNU Awk 4.0.2
  3. Copyright (C) 1989, 1991-2012 Free Software Foundation.
  4. $ awk 'BEGIN { OFMT = "%.15e"; print 4.483923595133619e+29 / 1000 }'
  5. 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:

  1. <strike>我认为您发现了GNU awk中的一个长期存在的错误。</strike>
  2. GNU awk的行为是正确的。
  3. 这里是[POSIX所说的内容](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html):
  4. > 具有与整数值完全相等的数值将通过等效于使用字符串`"%d"`作为`fmt`参数以及将要转换的数值作为第一个唯一的`expr`参数的`sprintf`函数(请参阅String Functions)来转换为字符串。
  5. 使用`printf`而不是设置`OFMT`不是解决gawk错误的方法。这是解决您的代码中的错误的方法。
  6. 任何足够大的浮点值都与整数完全相等。
  7. awk通过它们的值来区分整数和非整数的方式可能会让人感到困惑,如果您习惯了具有明确整数和浮点类型的语言。)
  8. 这里是发生的示例:
  9. ```bash
  10. $ cat foo.awk
  11. #!/usr/bin/awk -f
  12. BEGIN {
  13. OFMT="%.16e"
  14. for (i = 50; i <= 55; i ++) {
  15. x = 2 ** i - 0.5
  16. printf("2**%d - 0.5 = %.3f = ", i, x)
  17. print(x)
  18. }
  19. }
  20. $ ./foo.awk
  21. 2**50 - 0.5 = 1125899906842623.500 = 1.1258999068426235e+15
  22. 2**51 - 0.5 = 2251799813685247.500 = 2.2517998136852475e+15
  23. 2**52 - 0.5 = 4503599627370495.500 = 4.5035996273704955e+15
  24. 2**53 - 0.5 = 9007199254740992.000 = 9007199254740992
  25. 2**54 - 0.5 = 18014398509481984.000 = 18014398509481984
  26. 2**55 - 0.5 = 36028797018963968.000 = 36028797018963968
  27. $

最初我认为这是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

  1. 请注意,我已根据您的要求省略了代码部分,并只提供了翻译的内容。
  2. <details>
  3. <summary>英文:</summary>
  4. &lt;strike&gt;I believe you&#39;ve found a longstanding bug in GNU awk.&lt;/strike&gt;
  5. GNU awk is behaving correctly.
  6. Here&#39;s [what POSIX says](https://pubs.opengroup.org/onlinepubs/9699919799/utilities/awk.html):
  7. &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.
  8. 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.
  9. Any sufficiently large floating-point value is exactly equal to an integer.
  10. (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.)
  11. 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
$

  1. I initially thought this was a bug in gawk, and I submitted a bug report here:
  2. https://lists.gnu.org/archive/html/bug-gawk/2023-05/msg00010.html
  3. A reply from Andrew J. Schorr correctly says that this is the expected behavior.
  4. https://lists.gnu.org/archive/html/bug-gawk/2023-05/msg00011.html
  5. 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`.
  6. https://lists.gnu.org/archive/html/bug-gawk/2023-05/threads.html
  7. </details>
  8. # 答案2
  9. **得分**: 1
  10. I did run

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

  1. using **gawk 4.2.1** and it did give

448392359513361882871234560

  1. 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) }'

  1. using **gawk 4.2.1** did give

4.483923595133619e+26

  1. Observe need to apply line terminator yourself (`\n` means newline). Please try it with your `awk` and write if it does work as intended.
  2. [1]: https://www.gnu.org/software/gawk/manual/html_node/Printf-Examples.html
  3. <details>
  4. <summary>英文:</summary>
  5. I did run
  6. awk &#39;BEGIN { OFMT = &quot;%.15e&quot;; print 4.483923595133619e+29 / 1000 }&#39;
  7. using **gawk 4.2.1** and it did give
  8. 448392359513361882871234560
  9. I was unable to find reason for that, but determined that using [`printf`][1] does what you want, that is
  10. awk &#39;BEGIN { printf(&quot;%.15e\n&quot;, 4.483923595133619e+29 / 1000) }&#39;
  11. using **gawk 4.2.1** did give
  12. 4.483923595133619e+26
  13. Observe need to apply line terminator yourself (`\n` means newline). Please try it with your `awk` and write if it does work as intended.
  14. [1]: https://www.gnu.org/software/gawk/manual/html_node/Printf-Examples.html
  15. </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:

确定