How to format a number to show at least n decimals

Viewed 167

Is there a simple way to format a number to show at least n decimals ? If possible, using string templates and avoiding processing the string with code.

Expected results for 2 wanted decimals:

Value (type f) Expected output
4 4.00
0.4 0.40
0.04 0.04
0.004 0.004
0.0004 0.0004

I've only found ways to specify fixed decimal precision through string templates.

2 Answers

I'm not quite sure this can be achieved with string templates alone, as your requirements are quite special. However if you specify the number of decimals in the string template, the trailing zeros can be cut off with a regex:

DATA numbers TYPE STANDARD TABLE OF f.
numbers = VALUE #(
  ( 4 / 1     )
  ( 4 / 10    )
  ( 4 / 100   )
  ( 4 / 1000  )
  ( 4 / 10000 )
).

LOOP AT numbers INTO DATA(number).
  DATA(formatted) = replace(
    val = |{ number DECIMALS = 4 }|
    regex = '0{1,2}\z'
    with = ''
  ).

  WRITE formatted. NEW-LINE.
ENDLOOP.

Some comments:

  • The \z operator matches the end of a string
  • DECIMALS = 4 was an arbitrary choice based on the examples, you might want to choose a larger number there, and then adapt the regex to match 0{1, N - 2} zeros.
  • In a very new system you might want to have a look at the new PCRE

Here is a quick one-liner string template for you:

|{ <number> DECIMALS = COND #( WHEN <number> >= '0.01' THEN 2 ELSE strlen( substring_after( val = CONV string( <number> ) sub = '.' ) ) ) }|.

The decimal places here are dynamically calculated based on input number

DATA: decimal TYPE TABLE OF decfloat16.

APPEND 4 TO decimal.
APPEND '0.4' TO decimal.
APPEND '0.04' TO decimal.
APPEND '0.004' TO decimal.
APPEND '0.0004' TO decimal.

LOOP AT decimal ASSIGNING FIELD-SYMBOL(<dec>).
 WRITE |{ <dec> DECIMALS = COND #( WHEN <dec> >= '0.01' THEN 2 ELSE strlen( substring_after( val = CONV string( <dec> ) sub = '.' ) ) ) }|.
ENDLOOP.
Related