Classic Shell Scripting - Arnold Robbins [143]
[13] OFMT = "%25d" 2147483647 Expected 9007199254740991
[14] OFMT = "%25.0f" 9007199254740991
Evidently, despite the availability of 53-bit precision in floating-point values, on this platform nawk caps them at 32-bit integer limits for %d formats. Slightly different values were produced by runs of the same nawk version on other architectures. Example 9-8 shows the source for ofmt.awk.
Example 9-8. Testing the effect of OFMT
BEGIN {
test( 1, OFMT, 123.4567890123456789)
test( 2, "%d", 123.4567890123456789)
test( 3, "%e", 123.4567890123456789)
test( 4, "%f", 123.4567890123456789)
test( 5, "%g", 123.4567890123456789)
test( 6, "%25.16e", 123.4567890123456789)
test( 7, "%25.16f", 123.4567890123456789)
test( 8, "%25.16g", 123.4567890123456789)
test( 9, "%25d", 123.4567890123456789)
test(10, "%.25d", 123.4567890123456789)
test(11, "%25d", 2^31 - 1)
test(12, "%25d", 2^31)
test(13, "%25d", 2^52 + (2^52 - 1))
test(14, "%25.0f", 2^52 + (2^52 - 1))
}
function test(n,fmt,value, save_fmt)
{
save_fmt = OFMT
OFMT = fmt
printf("[%2d] OFMT = \"%s\"\t", n, OFMT)
print value
OFMT = save_fmt
}
We found that output for this test was quite sensitive to particular awk implementations, and even different releases of the same one. For example, with gawk, we get:
$ gawk -f ofmt.awk
...
[11] OFMT = "%25d" 2147483647 Expected right-adjusted result
...
[13] OFMT = "%25d" 9.0072e+15 Expected 9007199254740991
...
The informal language definition in the 1987 awk book specifies the default value of OFMT, but makes no mention of the effect of other values. Perhaps in recognition of implementation differences, POSIX says that the result of conversions is unspecified if OFMT is not a floating-point format specification, so gawk's behavior here is allowed.
With mawk, we find:
$ mawk -f ofmt.awk
...
[ 2] OFMT = "%d" 1079958844 Expected 123
...
[ 9] OFMT = "%25d" 1079958844 Expected 123
[10] OFMT = "%.25d" 0000000000000001079958844 Expected 00...00123
[11] OFMT = "%25d" 2147483647 Expected right-adjusted result
[12] OFMT = "%25d" 1105199104 Expected 2147483648
[13] OFMT = "%25d" 1128267775 Expected 9007199254740991
...
There are evidently inconsistencies and idiosyncrasies in the handling of output of large numbers with the formats %d and, in separate tests, %i. Fortunately, you can get correct output from all awk implementations by using a %.0f format instead.
* * *
[4] Originally, OFMT served for both output and string conversions, but POSIX introduced CONVFMT to separate their quite distinct purposes. Most implementations now have both, but SGI IRIX and Sun Solaris /usr/bin/nawk lack CONVFMT.
Numeric Functions
awk provides the elementary numeric functions listed in Table 9-5Table 9-5. Most of them are common to many programming languages, and their accuracy depends on the quality of the underlying native mathematical-function library.
Table 9-6. Elementary numeric functions
Function
Description
atan2( y, x )
Return the arctangent of y/x as a value in - to +.
cos( x )
Return the cosine of x (measured in radians) as a value in -1 to +1.
exp( x )
Return the exponential of x, e x.
int( x )
Return the integer part of x, truncating toward zero.
log( x )
Return the natural logarithm of x.
rand( )
Return a uniformly distributed pseudorandom number, r, such that 0 r < 1.
sin( x )
Return the sine of x (measured in radians) as a value in -1 to +1.
sqrt( x )
Return the square root of x.
srand( x )
Set the pseudorandom-number generator seed to x, and return the current seed. If x is omitted, use the current time in seconds, relative to the system epoch. If srand( ) is not called, awk starts with the same default seed on each run; mawk does not.
The pseudorandom-number generator functions rand() and srand( ) are the area of largest variation in library functions in different awk implementations because some of them use native system-library functions instead of their own code, and the pseudorandom-number