3

Was wondering if someone could help me out. Perhaps something is lurking in the source code, which unfortunately I am not literate enough just yet with C to catch what's causing this:

I run the following awk script as something of a test harness to illustrate this behaviour:

#! /usr/bin/env -S awk -E

BEGIN {
  OFMT = "%2.3e"
  CONVFMT = "%2.3e"

  print "gawk version:", PROCINFO["version"]

}

{
  for (f=1; f<=NF; f++) {
    print ""
    print "No modification:", typeof($f), $f
    print "Casting strnum to number via OFMT (" OFMT ") with 0+$" f ":",
      typeof(0+$f), 0+$f
    print "Casting strnum to string via CONVFMT (" CONVFMT ") with \"\" 0+$" f ":",
      typeof("" 0+$f), "" 0+$f
    print "Using strtonum():", strtonum($f)
    printf "Explicitly formatting as %%2.3e using printf: %2.3e\n", $f
  }
    print ""

  # "Born" a number (i.e., no conversion from strnum)
  x = 32553225
  print typeof(x), x
  # Now give it a fractional part
  x += 0.1
  print typeof(x), x
}
$ ./ofmt_test.awk <<< '236437734634 236437734634.000 236437734634.001'
gawk version: 4.2.1

No modification: strnum 236437734634
Casting strnum to number via OFMT (%2.3e) with 0+$1: number 236437734634
Casting strnum to string via CONVFMT (%2.3e) with "" 0+$1: string 236437734634
Using strtonum(): 236437734634
Explicitly formatting as %2.3e using printf: 2.364e+11

No modification: strnum 236437734634.000
Casting strnum to number via OFMT (%2.3e) with 0+$2: number 236437734634
Casting strnum to string via CONVFMT (%2.3e) with "" 0+$2: string 236437734634
Using strtonum(): 236437734634
Explicitly formatting as %2.3e using printf: 2.364e+11

No modification: strnum 236437734634.001
Casting strnum to number via OFMT (%2.3e) with 0+$3: number 2.364e+11
Casting strnum to string via CONVFMT (%2.3e) with "" 0+$3: string 2.364e+11
Using strtonum(): 2.364e+11
Explicitly formatting as %2.3e using printf: 2.364e+11

number 32553225
number 3.255e+07

So OFMT has no effect on the first large number (236437734634), but does seem to work with an explicit conversion in a printf statement. So I added .000 as a fractional part, which has no effect. Then I change that to .001 instead, and everything that didn't work with OFMT before now does?

I added an "independent" test case at the end, to rule out conversion from the strnum type as a cause. But the same effect occurs.

What is going on here where OFMT requires a nonzero fractional portion after the decimal, but an explicit format conversion to %e does not?

1 Answer 1

1

I saw this about CONVFMT in the POSIX Extended description:

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 "%d" as the fmt argument and the numeric value being converted as the first and only expr argument. Any other numeric value shall be converted to a string by the equivalent of a call to the sprintf function with the value of the variable CONVFMT as the fmt argument and the numeric value being converted as the first and only expr argument.

That pretty much describes what you're seeing here, and in the section on Output Statements:

All expression arguments shall be taken as strings, being converted if necessary; this conversion shall be as described in Expressions in awk, with the exception that the printf format in OFMT shall be used instead of the value in CONVFMT.

So, there we have it.

3
  • So if I understand it correctly, if it's an integer (even with some decimal precision), it remains one and does not go through either OFMT or CONVFMT? It's just surprising because I hadn't seen mention of this behavior anywhere (except now with what you posted). Usually caveats like this are mentioned when discussing OFMT and CONVFMT, but even in Arnold Robbins' Effective Awk Programming (where he's pretty thorough in pointing out unexpected behavior), it's not mentioned that I can see. TIL. Commented May 11, 2020 at 17:21
  • 2
    @CalvinBroadus It's also mentioned in the gawk manpage (search for "integral values are always converted as integers").
    – user313992
    Commented May 11, 2020 at 17:24
  • 1
    Yes, the last paragraph (dark corner) of 6.1.4.1 How awk Converts Between Strings and Numbers
    – muru
    Commented May 11, 2020 at 17:28

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .