Formatting xsd:double/float Values

Overview

Formatted numeric strings may have one of two forms: decimal notation (no exponent) or scientific notation (“E” notation). Scientific notation uses the form:

     [sign] mantissa E [sign] exponent

where mantissa is written in decimal notation, and exponent is an integer. The choice of decimal or scientific notation depends on the choice of exponent and on the expPresent parameter. By default, if the selected exponent is zero, the exponent is not shown (resulting in decimal notation). However, expPresent can be used to force display of the exponent, even when it is zero.

Overview of Options

totalDigits

integerMaxDigits

fractionDigits

These each limit the number of digits, either overall or in the integer or fraction part. They do not count leading zeros in the integer part, nor trailing zeros in the fraction part.

totalDigits, if specified must be at least 1.

integerMaxDigits and fractionDigits must be zero or more.

Note that the default for totalDigits is based on the datatype (double vs. float).

integerMinDigits This specifies the minimum number of digits to display in the integer part. If necessary, leading zeros are added. Using 0 means that the integer part, if 0, will not be displayed. Using 1 forces the display of a leading zero when the integer part is 0. The default value is 1. Note that integerMinDigits > integerMaxDigits is allowed (this will force some leading zeros).
fractionMinDigits This specifies the minimum number of digits to display in the fraction part. If necessary, trailing zeros are added. Note that fractionMinDigits > fractionDigits is allowed (this will force some trailing zeros). This option may produce strange looking results, as it may make a number appear to be more precise when digits have been rounded away. For example, we may round 12.345 to 12.35 due to a totalDigits setting of 4, but format this as “12.3500” due to a fractionMinDigits setting of 4.

expMinValue

expMaxValue

These specify exponential notation and control the range of exponents that may be used. The location of the decimal point in the mantissa is adjusted accordingly. When used, integerMaxDigits is ignored.
expSymbol Specify use of 'E' or 'e' for the exponent symbol. Specify '0' to prevent falling back on exponential notation for large magnitude values (see details in the section on Standard Decimal Notation, below).

signPresent

expSignPresent

Specify 1 or true to force the display of signs.
expPresent Specify 1 or true to force the display of a zero exponent. Note that this will force display of a zero exponent even if decimal notation as been selected.
expDigits The minimum number of digits to use in the exponent. If expDigits >= 1 is specified, this option forces exponential notation. If specified as 0, this option forces decimal notation.
pointPresent Specify 1 or true to force the display of the decimal point. Note that specifying fractionMinDigits > 0 will also force the display of the decimal point.

Exponential Notation: Method 1

The first way to specify exponential notation is by specifying at least one of the expMinValue or expMaxValue options.

If possible, the mantissa will be normalized such that 1 mantissa 10 (“normalized scientific notation”). If that requires an out-of-range exponent, then expMinValue/expMaxValue will be used for the exponent.

When either of these options (expMinValue or expMaxValue) are specified, the integerMaxDigits setting is ignored.

We attempt to honor the totalDigits setting by rounding off fractional digits of the mantissa. This is not possible, when expMaxValue is specified, for values such that |value| > 10totalDigits + expMaxValue. In that case, we will round integer digits to zero. For example, with totalDigits=2, expMaxValue=3, and value = 234567, the formatted result would be “230E3”.

The fractionDigits setting is always honored. Both fractionDigits and totalDigits may cause rounding off of fractional digits in the mantissa.

Note that using expMinValue may cause some smaller values to round to zero. In particular, values such that |value| < 510expMinValue - fractionDigits - 1 will round to zero (substitute totalDigits for fractionDigits, if fractionDigits was not specified). For example, suppose expMinValue = -2 and consider the value 4.23E-6. This value is precisely .000423E-2, which is formatted as “0E-2”, given totalDigits (or fractionDigits) = 3. Likewise, 4.567 rounds to “0E3” with expMinValue = 3 and totalDigits = 2 (4.567 = .004567E3).

To summarize, using expMinValue and expMaxValue allows you to fix the exponent range, but a side effect is that it may present fewer significant digits than with normalized scientific notation. However, note that these rules imply that all values where 10expMinValue |value| 10 expMaxValue + 1 will be presented in normalized scientific notation.

Tip

If you specify expMaxValue = 0 and expPresent=false, if 1 |value| 10totalDigits , the value will appear in decimal notation (the exponent will be 0 and hidden), while smaller values will use normalized scientific notation. Larger values, however, will appear in decimal notation with trailing zeros in the integer part (e.g. 8900000).

Exponential Notation: Method 2

The second way to specify exponential notation is through the use of the expDigits option. If you specify expDigits 1, then exponential notation will be used. The integerMaxDigits option controls the location of the decimal point and thus the choice of exponent. You must not specify either the expMinValue or the expMaxValue for this method.

By default (i.e., when no integerMaxDigits value is specified), the exponent will be normalized such that 1 |mantissa| < 10 . However, if you specify integerMaxDigits 0, this will affect the location of the decimal point, and thus the choice of exponent.

If you specify integerMaxDigits = 0, the integer part will be 0. Whether this digit is displayed or not depends on the integerMinDigits value ( 1 means a leading zero).

If you specify integerMaxDigits = 1, the default behavior results (normalized exponent).

If you specify integerMaxDigits > 1, we have some freedom on where to place the decimal point. We follow these rules:

  • Use at least 1 integer digit.

  • Use at least as many integer digits as totalDigits – fractionDigits. This avoids losing significant digits due to rounding.

  • If integerMinDigits > 0 is specified and using this many integer digits does not require a negative exponent, use at least this many integer digits. If this does require using a negative exponent, and some lesser number of integer digits does not, use at least the lesser number of digits. This avoids unnecessary padding with leading zeros, but also avoids moving the decimal point beyond its “natural” location (where it would appear in decimal notation).

  • Use no more than the number of integer digits prescribed by the preceding rules, and of course, no more than integerMaxDigits.

Specifying integerMinDigits > integerMaxDigits forces padding with at least 1 leading zero and is allowed. Using totalDigits or fractionDigits will cause rounding after the appropriate number of digits. Some examples:

totalDigits fractionDigits integerMaxDigits integerMinDigits value result
7 7 1 3 456.789 “004.56789E2”
7 7 2 3 456.789 “004.56789E2”
7 7 2 2 456.789 “045.6789E1”
7 4 4 0 9876.54321 “987.6543E1”

Standard Decimal Notation

If you specify expDigits = 0 and do not specify either expMinValue or expMaxValue, decimal notation will be used. In this case, values should be constrained as follows:

  • |value| < 10totalDigits

  • |value| < 10integerMaxDigits (if integerMaxDigits is specified)

If either of these constraints is violated, rather than produce an error (as would be the case for xsd:decimal types), we have fall-back behavior, depending on the expSymbol option:

  • If expSymbol is set to '0', then we will format the value in decimal notation, using as many integer digits as allowed, and then as many trailing zeros as needed to indicate the correct magnitude of the number.

  • Otherwise, we will format the value using exponential notation, with as many integer digits as allowed (getting as close to the decimal representation as possible) and an exponent that conveys the magnitude. In this case, the extra digits fall into the fraction part, which is rounded away.

Fractional digits will be rounded, based on totalDigits and/or fractionDigits. Values, such that |value| < 510-fractionDigits - 1 , will round to zero.

Mixed Notation

If you do not specify expMinValue, expMaxValue, or expDigits, then mixed notation is used. Mixed notation basically means that we use exponential notation with a normalized exponent, except that for some values, we use an exponent of zero (which is only displayed if expPresent is true).

Use an exponent of zero iff: 1 |value| 1010 . Otherwise, use the normalized exponent.

Consider carefully the use of integerMaxDigits or fractionDigits with mixed notation, as the notation affects rounding. For example, 0.1235 is rounded to “0.124” when using 3 fraction digits in decimal notation, but is presented without rounding when using exponential notation with 3 fraction digits: “1.235E-1”. With mixed notation, rounding will not occur in the same decimal location for all numbers, neither will it occur after a given number of significant digits for all numbers. Trailing integer zeros will be used if either of the following conditions occur:

  • |value| 10totalDigits

  • |value| 10integerMaxDigits (if integerMaxDigits is specified)