Version 6 of Floating-point formatting

Updated 2005-12-17 00:39:58

Arjen Markus (11 february 2003) I had a question from a customer about numbers that were displayed with too many digits, like "28.000" instead of "28.0". So, this raised the question: what can we do to make the appearance of (floating-point) numbers more elegant?

As it turns out, the format command has a lot of options, one of them is the # attribute to %g. Now, if all you have is the textual description of the effects, you will be very puzzled indeed.

So, here is a little script that examines the effects:

   # Check the effects of the various formats for floating-point numbers
   #
   foreach value {1.0 -1.0 1.01 -1.01 0.00001 -0.00001 1000000.0 -1000000.0} {
      set result ""
      foreach form {%g %-g %6g %6.4g %#.4g %06g %-6g} {
         append result [format " >$form<" $value]
      }
    puts "Value $value: $result"
   }

I have reformatted the output a bit, to get the following table:

  Formats:           %g       %-g       %6g       %6.4g     %#.4g        %06g   %-6g
  Value 1.0:         >1<      >1<       >     1<  >     1<  >1.000<      >000001< >1     <
  Value -1.0:        >-1<     >-1<      >    -1<  >    -1<  >-1.000<     >-00001< >-1     <
  Value 1.01:        >1.01<   >1.01<    >  1.01<  >  1.01<  >1.010<      >001.01< >1.01  <
  Value -1.01:       >-1.01<  >-1.01<   > -1.01<  > -1.01<  >-1.010<     >-01.01< >-1.01 <
  Value 0.00001:     >1e-05<  >1e-05<   > 1e-05<  > 1e-05<  >1.000e-05<  >01e-05< >1e-05 <
  Value -0.00001:    >-1e-05< >-1e-05<  >-1e-05<  >-1e-05<  >-1.000e-05< >-1e-05< >-1e-05<
  Value 1000000.0:   >1e+06<  >1e+06<   > 1e+06<  > 1e+06<  >1.000e+06<  >01e+06< >1e-06 <
  Value -1000000.0:  >-1e+06< >-1e+06<  >-1e+06<  >-1e+06<  >-1.000e+06< >-1e+06< >-1e+06<

However, there's more! The full format specification is huge and very, very complex. Here it is, bit by bit, aimed at people doing float formatting... (AM That complexity is precisely the reason to have this page - so you can see the effects :))

  • Start with a % symbol.
  • Add any optional positional specifier:
  1. If you don't want to use the next value off the argument list, add argListIndex and $ here. This is mainly useful for localized formats.
  • Add any optional flags:
  1. If you are going to make the space taken up by the field (potentially) larger than required to always hold the value and you want the field left-justified, add a - here.
  2. If you always want a sign, add a + here.
  3. If you want a space when the number isn't negative, add a space character here. Don't mix with the +.
  4. If you want to pad out with zeroes, not spaces, add a 0 here.
  5. If you want to use the alternate form, add a # here. This guarantees you get a decimal point and, for the g conversion guarantees you a full set of zeroes after the decimal point.
  • Add any optional field width:
  1. If you want to specify a minimum field width (as used in many of the examples above) put the (decimal) width of the field here. You can also take this value as an argument to [format] using a * instead.
  • Add any optional precision in either the form .number or .* (the latter if you want to take the value as an argument to [format], as with the field width above):
  1. If you are using the g conversion, you can say the maximum total number of digits to appear (excluding the exponent)
  2. If you are using the e or f conversions, you can say the number of digits to appear after the decimal point.
  • Floats don't use length modifiers in Tcl. They're only used for integer values.
  • Finally, add the conversion specifier which marks the end of the format.
  1. f uses normal notation.
  2. e uses scientific notation.
  3. E is just like e but uses a capital letter for the exponent char.
  4. g uses either normal or scientific notation, depending on the scale of the number.
  5. G is just like g but uses a capital letter for the exponent char (if printed).

So, if we want a left formatted normal float in a gap at least 8 characters wide and to not have the start of the number jump around when going between positive and negative numbers while taking the number of values after the decimal point from a variable, you should use the format "%- 8.*f" (and yes, the space is significant.)


[ Arts and crafts of Tcl-Tk programming - Category String Processing ]