Tutorial for decimals in GMT?

In the docs I often see things like %6.4f, %.16lg, %.12g, etc. I know that it is to control the decimals of numbers, but I don’t understand what does it means. I usually do try and error until I get the decimals that I want. Where I can read about that syntax? Is that C language printf? Could you share any good link/tutorial? Thanks in advance.

Yes, this is like C’s printf (or bash’s printf as the examples below). You could check out https://linux.die.net/man/3/printf. I’ve also struggled with this. I made a cheat sheet for myself, maybe it is of use.

For your specific case, controlling decimals, it’s like this: %[width].[no of decimals][type]

$ printf "%g \n" "3.14159265358979323"
3.14159 
printf "%10.3g \n" "3.14159265358979323"
      3.14 
$ printf "%10.8g \n" "3.14159265358979323"
 3.1415927 
$ printf "%.16g \n" "3.14159265358979323"
3.141592653589793

I’m confused though; why does printf "%10.3g \n" "3.14159265358979323" print two decimals and not three? Maybe some divine C programmer can answer. EDIT: changing the type from g to f gives the expected result.

| printf    | %[-][n][.][n][h,l]cc                                 |
|-----------|------------------------------------------------------|
| %         | conversion specification                             |
| -         | specifies left adjustment                            |
| n         | specifies the minimum field width                    |
| .         | separates the field width from the precision         |
| n         | max number of chars (string)                         |
|           | OR number of digits after decimal point (float)      |
|           | OR min. number of digits (int)                       |
| h         | print int as short                                   |
| l         | (letter ell) print int as long                       |
| cc        | conversion character                                 |
|           |                                                      |
| Character | Argument type; Printed As                            |
| d,i       | int (decimal number)                                 |
| o         | int; unsigned octal number                           |
| x,X       | int; unsigned hexadecimal number                     |
| u         | int; unsigned decimal number                         |
| c         | int; single character                                |
| s         | char *; (tekststreng)                                |
| f         | double; [-] m.dddddd , d = precision (6).            |
| e,E       | double; [-] m.dddddd e+/- xx or [-] m.dddddd E+/- xx |
| g,G       | double; use %e or %E if the exponent is less than -4 |
| p         | void *; pointer                                      |
| %         | no argument is converted; print a %                  |
1 Like

See the Matlab manual for fprintf

The %g specifier is tricky (but often the most usefull one) and many manuals about it are wrong. See this SO question/answer. The best thing on %g is that it removes trailing zeros.

julia> @printf("%.15g", 0.3333)
0.3333
julia> @printf("%.15f", 0.3333)
0.333300000000000
1 Like

Maybe it would be a nice addition to the man-pages to include a small paragraph on how to specify these printf templates. They are mentioned two times in https://docs.generic-mapping-tools.org/6.1/gmt.conf.html#format-parameters:

FORMAT_FLOAT_MAP

Format (C language printf syntax) to be used when plotting double precision floating point numbers along plot frames and contours. For geographic coordinates, see [FORMAT_GEO_MAP](https://docs.generic-mapping-tools.org/6.1/gmt.conf.html#term-FORMAT_GEO_MAP). [%.12lg].

FORMAT_FLOAT_OUT

Format (C language printf syntax) to be used when printing double precision floating point numbers to output files. For geographic coordinates, see [FORMAT_GEO_OUT](https://docs.generic-mapping-tools.org/6.1/gmt.conf.html#term-FORMAT_GEO_OUT). [%.12lg]. To give some columns a separate format, supply one or more comma-separated *cols*:*format* specifications, where *cols* can be specific columns (e.g., 5 for 6th since 0 is the first) or a range of columns (e.g., 3-7). The last specification without column information will override the format for all other columns. Alternatively, you can list N space-separated formats and these apply to the first N columns.

Yes, that would be a nice addition. Would you mind making a pull request. Add it to FORMAT_FLOAT_OUT and just refer to FORMAT_FLOAT_OUT from FORMAT_FLOAT_MAP.

1 Like

I thought the whole point of using printf-type of output was that you always know what you get. With %g, this does not seem to be the case; what you get (length and precision) depends of the input number.

I read through the SO post you shared. I feel a bit wiser, but still not quite ‘arrived’. Based on purely empirical example:

$ printf "%.5g\n" "2.33335234"
2.3334
$ printf "%.5f\n" "2.33335234"
2.33335

Explanation based on my primitive, outdated neural network:

  • %.ng - round off the the number based on the nth-precision number and give (n-1) decimals.
  • %.nf - print n decimals - what I specified

What is the rationale of choosing %g over %f as default? Remove traliing zeros, as Joaquim mentioned? And why include l (as in %.12lg)? Based on my interpretation this causes int to be printed as long, but we’re not dealing with int’s here, no? From https://en.wikipedia.org/wiki/Printf_format_string:

For floating point types, this [l] is ignored. float arguments are always promoted to double when used in a varargs call.

Again, sorry, no

>> fprintf('%.5g\n', 10.3333333)
10.333
>> fprintf('%.3g\n', 1/30)
0.0333
>> fprintf('%.5g\n', 10.3333333)
10.333
>> fprintf('%.3g\n', 1/30)
0.0333
>> fprintf('%.4g\n', 12.001)
12
>> fprintf('%.5g\n', 12.001)
12.001

Note that the Matlab page says %g prints the significant digits not the number of decimal digits. Except that it doesn’t print the trailing zeros, even when they are significant (the two 0s in 12.00)

I use %g specially when I want to convert numbers into strings (for example when building -R option). Otherwise use what you feel it’s better for your case.

Thanks Joaquim, for enlightening me.