Docs / Mapper Arithmetic
Calculate decimal values in X12 Mapper
Divide quantities and amounts without losing their fractional part. Use explicit rounding to produce the decimal places required by your partner or output format.
Keep the fractional result
The / operator returns the exact decimal result whenever its decimal expansion terminates. Exact results retain their precision even when they need more than 34 significant digits. The decimal places written in the operands do not limit the result.
println(5/2) // 2.5
println(1/8) // 0.125
println(toNumber("1e-2")/2) // 0.005
println(0.1+0.2) // 0.3
The mapper uses decimal arithmetic. Numeric X12 elements can participate directly in calculations; use toNumber(...) to convert numeric text explicitly.
Repeating results use 34 significant digits
Some quotients, such as 1/3, have an infinite decimal expansion. The mapper rounds these results to 34 significant digits using HALF_UP rounding: round to the nearest value, with ties rounded away from zero.
Significant digits count meaningful digits before and after the decimal point, excluding leading zeros. For example, 123.456 and 0.000123456 both have six significant digits. This rule preserves useful precision for small quantities as well as large amounts; it is not a fixed limit of 34 decimal places.
println(1/3) // 0.3333333333333333333333333333333333
println(2/3) // 0.6666666666666666666666666666666667
println(100/3) // 33.33333333333333333333333333333333
Repeating results remain approximations. Multiplying a rounded quotient back by its divisor does not always recover the original value exactly:
println((1/3)*3) // 0.9999999999999999999999999999999999
println(round((1/3)*3, 2)) // 1.00
Keep decimal places when adding amounts
Addition preserves the greater number of decimal places from its numeric operands, including when the result is a whole number. Variables, parentheses, and addition assignment follow the same rule:
first=1.00
second=2.00
println(first+second) // 3.00
println((first+second)*1) // 3.00
first+=second
println(first) // 3.00
This preserves formatting without changing numeric equality: 3.00 and 3 are equal as numbers. Use round(...) when the output requires a specific number of decimal places.
Choose the decimal places for an output field
round(number, scale) rounds to the requested number of decimal places using HALF_UP. A scale of 0 rounds to a whole number; a scale of 2 retains two decimal places. Negative scales round to tens, hundreds, and so on.
println(round(1/3, 2)) // 0.33
println(round(5/2, 0)) // 3
println(round(-5/2, 0)) // -3
println(round(5/2, 2)) // 2.50
println(round(1/8, 2)) // 0.13
For example, divide a total amount by the quantity and round the resulting unit price:
total=12.50
quantity=5
unitPrice=round(total/quantity, 2)
toJson({"unitPrice":unitPrice}) // {"unitPrice":2.50}
Round at the point required by the business rule. Rounding each line amount can produce a different total from rounding once after adding all the lines. JSON consumers may display a numeric 2.50 as 2.5; those are the same numeric value.
Use the same rule with division assignment
value /= divisor uses the same precision rule as value = value / divisor:
ratio=1
ratio/=3
println(ratio) // 0.3333333333333333333333333333333333
println(round(ratio, 2)) // 0.33
Division by zero is an error for both / and /=. Guard a quantity that may be zero when the mapping has a defined fallback:
total=12.50
quantity=0
unitPrice=quantity==0 ? 0 : round(total/quantity, 2)
print(unitPrice) // 0
The conditional expression evaluates only the selected branch, so the division is skipped when the quantity is zero.
Check your calculation on a sample
Run the calculation in the Mapper workspace and save representative quantities and amounts as mapping test cases. See Mapper Comparisons for numeric equality and text matching, and the Mapper Built-ins reference for round and toNumber.