TheAlgorithms/Python · error · ValueError

Profit can not be negative.

Error message

Profit can not be negative.

What it means

Thrown by calc_profit() when any element of profit is negative. The greedy algorithm's correctness argument (take items by best profit/weight ratio) assumes non-negative values; a negative profit item could be selected and subtract from the total, so the function validates all profits upfront.

Source

Thrown at knapsack/greedy_knapsack.py:38

def calc_profit(profit: list, weight: list, max_weight: int) -> int:
    """
    Function description is as follows-
    :param profit: Take a list of profits
    :param weight: Take a list of weight if bags corresponding to the profits
    :param max_weight: Maximum weight that could be carried
    :return: Maximum expected gain

    >>> calc_profit([1, 2, 3], [3, 4, 5], 15)
    6
    >>> calc_profit([10, 9 , 8], [3 ,4 , 5], 25)
    27
    """
    if len(profit) != len(weight):
        raise ValueError("The length of profit and weight must be same.")
    if max_weight <= 0:
        raise ValueError("max_weight must greater than zero.")
    if any(p < 0 for p in profit):
        raise ValueError("Profit can not be negative.")
    if any(w < 0 for w in weight):
        raise ValueError("Weight can not be negative.")

    # List created to store profit gained for the 1kg in case of each weight
    # respectively.  Calculate and append profit/weight for each element.
    profit_by_weight = [p / w for p, w in zip(profit, weight)]

    # Creating a copy of the list and sorting profit/weight in ascending order
    sorted_profit_by_weight = sorted(profit_by_weight)

    # declaring useful variables
    length = len(sorted_profit_by_weight)
    limit = 0
    gain = 0
    i = 0

    # loop till the total weight do not reach max limit e.g. 15 kg and till i<length
    while limit <= max_weight and i < length:

View on GitHub (pinned to f5988cc097)

Solutions

  1. Filter or fix negative profits before the call: drop the item, or convert cost to value explicitly if that is the intended semantics.
  2. Use None or NaN sentinels for missing data and sanitize at parse time.
  3. Add a data-quality assertion when building the lists from external data.

Example fix

# before
calc_profit([-10, 20, 30], [5, 5, 5], 100)  # ValueError

# after
pairs = [(p, w) for p, w in zip(profits, weights) if p >= 0]
calc_profit([p for p, _ in pairs], [w for _, w in pairs], 100)
Defensive patterns

Strategy: validation

Validate before calling

assert all(p >= 0 for p in profit), "profits must be non-negative"

Type guard

def all_profits_non_negative(profit: list[float]) -> bool:
    return all(isinstance(p, (int, float)) and p >= 0 for p in profit)

Try / catch

try:
    gain = calc_profit(profit, weight, max_weight)
except ValueError as e:
    if "Profit" in str(e):
        gain = calc_profit([max(p, 0) for p in profit], weight, max_weight)
    else:
        raise

Prevention

When it happens

Trigger: Calling calc_profit with a profits list containing a negative entry, e.g. calc_profit([-10, 20], [5, 5], 100). Typically the negative value is a cost or loss figure mixed into a value list.

Common situations: Feeding raw P&L data where losses are negative; missing abs() when converting costs to profits; sentinel -1 values for 'no data' items surviving into the algorithm.

Related errors


AI-assisted analysis of TheAlgorithms/Python@f5988cc097 (2026-08-14). Data as JSON: /api/errors/1f4e81735ce4ba05. Report an issue: GitHub.