Avoid floating-point and use integers or the decimal
module to ensure precision in applications that require high accuracy, such as in financial or banking computations.
In Python, floating-point types are constrained by a fixed number of binary mantissa bits, typically allowing for around seven decimal digits of precision (24-bit values). Consequently, they are not well-suited for representing surds, such as √7
or π
with full accuracy. Additionally, due to their binary nature, floating-point types are incapable of exactly terminating decimals in base 10
, such as 0.3
, which has a repeating binary representation.
To ensure precision in applications requiring high accuracy, such as in financial or banking computations, it is recommended to avoid using floating-point types. Instead, integers or more precise data types like the Decimal
class should be employed.
This noncompliant01.py
demonstrates the use of floating-point arithmetic to simulate purchasing items and subsequent
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Non-compliant Code Example """
BALANCE = 3.00
ITEM_COST = 0.33
ITEM_COUNT = 5
print(
f"{str(ITEM_COUNT)} items bought, ${ITEM_COST} each. "
f"Current account balance: "
f"${str(BALANCE - ITEM_COUNT * ITEM_COST)}"
)
The unprecise base 10
representation during the multiplication of 5
with 0.33
results in an account balance
of $1.34999999999999993
in the noncompliant01.py
code.
Example noncompliant01.py output:
5 items bought, $0.33 each. Current account balance: $1.34999999999999993
This compliant solution adheres more to standards by representing the account balance and item cost as integers
in cents instead of using dollars. This approach eliminates the imprecision associated with floating-point numbers:
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Non-compliant Code Example """
BALANCE = 300
ITEM_COST = 33
ITEM_COUNT = 5
print(
f"{str(ITEM_COUNT)} items bought, ${ITEM_COST / 100} each. "
f"Current account balance: "
f"${str((BALANCE - ITEM_COUNT * ITEM_COST) / 100)}"
)
Example compliant01.py
output:
5 items bought, $0.33 each. Current account balance: $1.35
This compliant solution adheres to standards by utilizing the imported Decimal
type, which allows for precise representation of decimal values. It’s important to note that, on most platforms, calculations using Decimal
tend to be less efficient compared to those using basic data types.
# SPDX-FileCopyrightText: OpenSSF project contributors
# SPDX-License-Identifier: MIT
""" Compliant Code Example """
from decimal import Decimal
BALANCE = Decimal("3.00")
ITEM_COST = Decimal("0.33")
ITEM_COUNT = 5
print(
f"{str(ITEM_COUNT)} items bought, ${ITEM_COST} each. "
f"Current account balance: "
F"${str(BALANCE - ITEM_COUNT * ITEM_COST)}"
)
Example compliant02.py
output:
5 items bought, $0.33 each. Current account balance: $1.35
Tool | Version | Checker | Description |
---|---|---|---|
Pylint | 2023.10.1 | Not Available | Not detected |
SEI CERT Oracle Coding Standard for Java | NUM04-J. Do not use floating-point numbers if precise computation is required |
The CERT C Secure Coding Standard | FLP02-C. Avoid using floating-point numbers when precise computation is needed, available from: https://wiki.sei.cmu.edu/confluence/pages/viewpage.action?pageId=87152394, [Accessed Dec 2024] |
ISO/IEC TR 24772:2010 | Floating-Point Arithmetic [PLF] |
[MITRE CWE Pillar] | CWE-682: Incorrect Calculation |
[MITRE CWE Base] | CWE - CWE-1339: Insufficient Precision or Accuracy of a Real Number |
[Bloch 2008] | Item 48, “Avoid float and double If Exact Answers Are Required” |
[Bloch 2005] | Puzzle 2, “Time for a Change” |
[IEEE 754] |