Symptom
When attempting to round the value 168830.365 to 2 decimal places in scripting workbench differs when using Python's round() function, returning .36, and using TagParserQuote.ParseString(<*ROUND()*>) returns .37.
Environment
SAP SALES CLOUD CPQ
Reproducing the Issue
- Open Script Workbench
- Execute parser_result = TagParserQuote.ParseString('<*ROUND(168830.365, 2)*>') and script_result = round(168830.365, 2)
- Verify that rounding result is different.
Cause
Python Behavior.
Resolution
- In Python 2.7, the built-in round(...) function uses "round half away from zero" strategy (e.g., 0.5 always goes up). However, due to floating-point binary representation, a number like 168830.365 is stored in memory as 168830.3650000000143..., causing it to round up to .37 even when Banker's Rounding is expected
- Python 3 (and IronPython 3 also) fixed this by implementing "Round Half to Even" (Banker's Rounding) as the native behavior for the round() function
- For IronPython 2 users, to ensure consistent and precise financial rounding (Banker's Rounding), use the Decimal.Round method (this is possible because C# Decimal is already available in scope, x = Decimal.Round(Decimal(168830.365), 2).
See Also
Keywords
formula builder, round, rounding discrepancy, banker’s rounding, round half to even, half away from zero, ctx tag, iron python 2, decimal.round, CPQ , KBA , CEC-SAL-CPQ , Sales Cloud CPQ , How To
Product
SAP CPQ 2024
SAP Knowledge Base Article - Public