Sometimes, it's necessary to write an authorization rule against numbers that contain decimal parts. For example, you may want to check if a currency field is greater than
"1.99", or compare the output from an ML-based risk scoring system which emits values such as
"0.9234". Cedar supports this using the Decimal type with a fixed precision, where the maximum number of digits after the decimal is four.
In many other programming environments, there is an alternative representation of numbers known as floating-point which allows for bigger or smaller values with different degrees of precision. For example, a floating point number might approximate the value of pi with a sequence of digits such as
"3.141592653589793…" up to the maximum size allowed by the data type, often 64 bits or 15 decimal digits.
Cedar does not support floating-point numbers. The reason is because floating-point numbers, by their nature, are imprecise, and imprecision is not a desirable property of an authorization system. To illustrate this point, consider the following test:
0.1 + 0.2 == 0.3. This appears as if it should evaluate to true. But, in most programming languages, it doesn't. This blog post documents the result of the operation in a variety of different programming languages. The reason this occurs is because fractions such as
1/20 do not have a precise binary representation. Floating-point arithmetic approximates these values with a limited degree of precision.
Floating-point can lead to other quirks as well. For example
Floating-point is a well-defined and a very useful format in many other programming contexts. We elected not to include it in Cedar not because it’s a “bad” format, but because we think it’s a bad idea to use this kind of arithmetic for authorization decisions.
Because of this, Cedar also does not include mathematical operators such as division that return floating-point values. For example, the operation
1 / 3 would necessitate a floating-point value for the result. Cedar also does not allow multiplication with Decimal types, such as
1 * decimal("0.3"), as this would lead to the same outcome.
For additional information on the Cedar
Decimal type and other operators, see the documentation.
Decimal supports the following operations:
decimal("0.3") == decimal("0.3") //true decimal("0.3") != decimal("0.4321") //true decimal("0.3").lessThan("922337203685477.5807") //true decimal("0.3").lessThanOrEqual("0.300") //true decimal("0.3").greaterThan("-4.82") //true decimal("0.3").greaterThanOrEqual("00.30") //true