Built-ins for numbers

Related FAQs: Do you have things like 1,000,000 or 1 000 000 instead of 1000000, or something like 3.14 instead of 3,14 or vice versa? See this and this FAQ entry, also note the c built-in above.

abs

Note:

This built-in exists since FreeMarker 2.3.20.

Gives the absolute value of a number. For example x?abs , if x is -5, will evaluate to 5.

c (when used with numerical value)

Note:

This built-in exists since FreeMarker 2.3.3.

This built-in converts a number to string for a "computer language" as opposed to for human audience. That is, it formats with the rules that programming languages used to use, which is independent of all the locale and number format settings of FreeMarker. It always uses dot as decimal separator, and it never uses grouping separators (like 3,000,000), nor exponential form (like 5E20), nor superfluous leading or trailing 0-s (like 03 or 1.0), nor + sign (like +1). It will print at most 16 digits after the decimal dot, and thus numbers whose absolute value is less than 1E-16 will be shown as 0. This built-in is crucial because be default (like with ${x}) numbers are converted to strings with the locale (language, country) specific number formatting, which is for human readers (like 3000000 is possibly printed as 3,000,000). When the number is printed not for human audience (e.g., for a database record ID used as the part of an URL, or as invisible field value in a HTML form, or for printing CSS/JavaScript numerical literals) this built-in must be used to print the number (i.e., use ${x?c} instead of ${x}), or else the output will be possibly broken depending on the current number formatting settings and locale (like the decimal point is not dot, but comma in many countries) and the value of the number (like big numbers are possibly ``damaged'' by grouping separators).

If the incompatible_imporvements FreeMarker configuration setting is set to 2.3.21 (or higher), this built-in will return "INF", "-INF" and "NaN" for positive/negative infinity and IEEE floating point Not-a-Number, respectively. These are the XML Schema compatible representations of these special values. (Earlier it has returned what java.text.DecimalFormat did with US locale, none of which is understood by any (common) computer language.)

Note that this built-in also works on booleans.

is_infinite

Note:

This built-in exists since FreeMarker 2.3.20.

Tells if a number is floating point infinite (according to IEEE 754). For example, someNumber?is_infinite evaluates to true or false depending on if the value of someNumber is infinite or not. Of course, if the underlying number is not of floating point type, this will always return false.

is_nan

Note:

This built-in exists since FreeMarker 2.3.20.

Tells if a number is floating point NaN (according to IEEE 754). For example, someNumber?is_nan evaluates to true or false depending on if the value of someNumber is NaN or not. Of course, if the underlying number is not of floating point type, this will always return false.

lower_abc

Note:

This built-in exists since FreeMarker 2.3.22.

Converts 1, 2, 3, etc., to the string "a", "b", "c", etc. When reaching "z", it continues like "aa", "ab", etc. This is the same logic that you can see in column labels in spreadsheet applications (like Excel or Calc). The lowest allowed number is 1. There's no upper limit. If the number is 0 or less or it isn't an integer number then the template processing will be aborted with error.

Example:

<#list 1..30 as n>${n?lower_abc} </#list>

Prints:

a b c d e f g h i j k l m n o p q r s t u v w x y z aa ab ac ad 

See also: upper_abc

round, floor, ceiling

Note:

The rounding built-ins exist since FreeMarker 2.3.13.

Converts a number to a whole number using the specified rounding rule:

  • round: Rounds to the nearest whole number. If the number ends with .5, then it rounds upwards (i.e., towards positive infinity)

  • floor: Rounds the number downwards (i.e., towards neagative infinity)

  • ceiling: Rounds the number upwards (i.e., towards positive infinity)

Example:

<#assign testlist=[
  0, 1, -1, 0.5, 1.5, -0.5,
  -1.5, 0.25, -0.25, 1.75, -1.75]>
<#list testlist as result>
    ${result} ?floor=${result?floor} ?ceiling=${result?ceiling} ?round=${result?round}
</#list>

Prints:

    0 ?floor=0 ?ceiling=0 ?round=0            
    1 ?floor=1 ?ceiling=1 ?round=1        
    -1 ?floor=-1 ?ceiling=-1 ?round=-1      
    0.5 ?floor=0 ?ceiling=1 ?round=1      
    1.5 ?floor=1 ?ceiling=2 ?round=2      
    -0.5 ?floor=-1 ?ceiling=0 ?round=0     
    -1.5 ?floor=-2 ?ceiling=-1 ?round=-1    
    0.25 ?floor=0 ?ceiling=1 ?round=0     
    -0.25 ?floor=-1 ?ceiling=0 ?round=0    
    1.75 ?floor=1 ?ceiling=2 ?round=2     
    -1.75 ?floor=-2 ?ceiling=-1 ?round=-2

These built-ins may be useful in pagination operations and like. If you just want to display numbers in rounded form, then you should rather use the string built-in or the number_format setting.

string (when used with a numerical value)

Converts a number to a string. It uses the default format that the programmer has specified via the number_format and the locale settings. You can also specify a number format explicitly with this built-in, as it will be shown later.

There are four predefined number formats: computer, currency, number, and percent. The exact meaning of these is locale (nationality) specific, and is controlled by the Java platform installation, rather than by FreeMarker, except for computer, which uses the same formatting as the c built-in. You can use these predefined formats like this:

<#assign x=42>
${x}
${x?string}  <#-- the same as ${x} -->
${x?string.number}
${x?string.currency}
${x?string.percent}
${x?string.computer}

If your locale is US English, this will print:

42
42
42
$42.00
4,200%
42

The output of first three expressions is identical because the first two expressions use the default format, which is "number" here. You can change this default using a setting:

<#setting number_format="currency">
<#assign x=42>
${x}
${x?string}  <#-- the same as ${x} -->
${x?string.number}
${x?string.currency}
${x?string.percent}

Will now output:

$42.00
$42.00
42
$42.00
4,200%

since the default number format was set to "currency".

Beside the three predefined formats, you can use arbitrary number format patterns written in Java decimal number format syntax:

<#assign x = 1.234>
${x?string["0"]}
${x?string["0.#"]}
${x?string["0.##"]}
${x?string["0.###"]}
${x?string["0.####"]}

${1?string["000.00"]}
${12.1?string["000.00"]}
${123.456?string["000.00"]}

${1.2?string["0"]}
${1.8?string["0"]}
${1.5?string["0"]} <-- 1.5, rounded towards even neighbor
${2.5?string["0"]} <-- 2.5, rounded towards even neighbor

${12345?string["0.##E0"]}

outputs this:

1
1.2
1.23
1.234
1.234

001.00
012.10
123.46

1
2
2 <-- 1.5, rounded towards even neighbor
2 <-- 2.5, rounded towards even neighbor

1.23E4

Note that as in FreeMarker foo.bar is equivalent with foo["bar"], you could also write x?string.currency as x?string["currency"], but of course that wouldn't be practical. But in the above examples we have to use the square bracket syntax, because the characters involved (numbers, dot, #) aren't allowed syntactically after the dot operator.

For historical reasons, you could also write things like x?string("0.#"), which does exactly the same as x?string["0.#"].

Following the financial and statistics practice, the rounding goes according the so called half-even rule, which means rounding towards the nearest ``neighbor'', unless both neighbors are equidistant, in which case, it rounds towards the even neighbor. This was visible in the above example if you look at the rounding of 1.5 and of 2.5, as both were rounded to 2, since 2 is even, but 1 and 3 are odds.

As it was shown for the predefined formats earlier, the default formatting of the numbers can be set in the template:

<#setting number_format="0.##">
${1.234}

outputs this:

1.23

Note that as number formatting is locale sensitive, the locale setting also plays role in the formatting:

<#setting number_format=",##0.00">
<#setting locale="en_US">
US people write:     ${12345678}
<#setting locale="hu">
German people write: ${12345678}

outputs this:

US people write:     12,345,678.00
German people write: 12.345.678,00

upper_abc

Note:

This built-in exists since FreeMarker 2.3.22.

Same as lower_abc, but converts to upper case letters, like "A", "B", "C", …, "AA", "AB", etc.