Use Integer Values and Decimal Values in Configurator Rules

Consider how your configurator rule uses integer values and decimal values.

You must make sure that the result of multiplying integer values in your rule doesn't exceed Java's integer limit. Constraint Definition Language (CDL) uses Java's Double data type to store a decimal value. Double has a much higher limit than Java's Integer data type. In some cases, a rule that you create in CDL might result in a value that exceeds the integer's limit.

The result of a mathematical operation in a configurator rule depends on each operand's data type. If each of your operands are an integer, and if the value after the operator is a constant integer, or if it references an attribute that contains an integer value, then the result will be an integer.

Scenario

Consider a scenario.

IntegerFeature (min = 0, max = 2,147,483,647)
DecimalFeature (min = 0, max = 999,999,999,999,999)

Assume you have this logic in your rule.

IntegerFeature * 400,000 = DecimalFeature

You might assume that you can specify any value for IntegerFeature as long as that value remains in IntegerFeature's range, and then store the result of your multiplication in DecimalFeature.

However, IntegerFeature and the constant value of 400,000 are each an integer, 400,000 is after the operator, so the result of the multiplication must be an integer, not a decimal, and it must not exceed IntegerFeature's maximum value. At runtime, if you set IntegerFeature to a value that exceeds 5,368, you'll have an error.

Runtime Math Result
5,368 multiplied by 400,000 equals 2,147,200,000. 2,147,200,000 is less than IntegerFeature's 2,147,483,647 maximum, so you're good to go.
5,369 multiplied by 400,000 equals 2,147,600,000. 2,147,600,000 exceeds IntegerFeature's 2,147,483,647 maximum, so you'll have an error.

Solutions

Convert an Operand to a Decimal

For example, change 400,000 to 400,000.0:

IntegerFeature * 400,000.0 = DecimalFeature
Another way is to multiply one of the operands by a very small value, such as 1.00000001. Multiplying by a small value will have a negligible affect on the result, but will help to avoid the problem. For example:
IntegerFeature * 1.00000001

Use a Decimal Feature or Supplemental Attribute

If you can't use a simple constant or a decimal value after the operator, then consider using a decimal feature instead of an integer feature.

If you can't use a decimal feature, then use a supplemental attribute that contains an integer instead of using the constant value. For example:
IntegerFeature * m1.suppAttrs["IntegerAttribute"] = DecimalFeature

Other Alternatives

Code Description

(IntegerFeature * SQRT(1)) * m1.suppAttrs["IntegerAttribute"] = DecimalFeature

The SQRT function will return a decimal.

(IntegerFeature * 1.00000001)) * m1.suppAttrs["IntegerAttribute"] =DecimalFeature The 1.00000001 constant is a decimal.

Modify the Sequence of Your Operands

If the solutions that we describe above don't work for you, then you can modify the sequence of your operands. The problem happens only when the value after the operator is static, so you can move that value to before the operator:

m1.suppAttrs["IntegerAttribute"] * IntegerFeature = DecimalFeature

Here's a more complex example:

Add &x.Quantity() * &x.suppAttrs["IntegerAttribute"] To DecimalFeature FOR
ALL &x IN {OptionClass.Options()}

You can rewrite it to avoid the problem:

Add (&x.Quantity() * SQRT(1)) * &x.suppAttrs["IntegerAttribute"] To
DecimalFeature FOR ALL &x IN {OptionClass.Options()}

Or, rewrite it this way:

Add &x.suppAttrs["IntegerAttribute"] * &x.Quantity() To DecimalFeature FOR
ALL &x IN {OptionClass.Options()}

The problem happens only when you multiply integer operands and the result overflows into a decimal. If the overflow doesn’t happen, then the sequence that you use for the operands doesn’t matter.