amount: BigNumeric
amount = 1234567890_1234567890_1234567890.123456789
The code above gives the error:
Failure to process Daml program, this feature is not currently supported.
Large BigNumeric (larger than Numeric) literals are not currently supported. Please construct the number from smaller literals.
Is there a different way to write BigNumerics?
I am using sdk 2.5.0
Iām focusing on the part of the error message that says large āliteralsā are not currently supported. That leads me to try thisā¦
1234567890e20 + 1234567890e10 + 1234567890e0 + 1234567890e-10 : BigNumeric
ā¦which results in your number.
There is probably a better way to āconstruct the number from smaller literalsā but the above is what comes to mind for me.
Thanks @WallaceKelly. Going by your approach, the widest number would be:
amount = 1e28 + 1e-37 : BigNumeric
Anything more on either side of the decimal is giving the same error.
The definition of BigNumerics in the docs is:
BigNumeric represents any positive or negative decimal number
with up to 2^15 digits before the decimal point,
and up to 2^15 digits after the decimal point.
These two definitely do not match, so I wonder if I am interpreting the definition incorrectly.
The limitations @WallaceKelly mentioned only applies to literals so fixed numbers that you have in your source code. The restrictions you mentioned apply to arbitrary values of type BigDecimal
. Those can be the result of computations on your literals. Here is an example of how you can construct the value you tried to write as a literal by building it up from smaller literals:
module Main where
import Daml.Script
test = script do
{- does not compile, literal too big
let amount: BigNumeric
amount = 1234567890_1234567890_1234567890.123456789
-}
-- This compiles. The 3 literals (lowerHalf, upperHalf and the multiplicator)
-- satisfy the restrictions. The resulting value `amount` is the result of a computation
-- not a literal in your source code and satisfies the more general constraints of BigNumeric
let lowerHalf = 1234567890.123456789 : BigNumeric
let upperHalf = 1234567890_1234567890.0 : BigNumeric
let amount = upperHalf * 10000000000.0 + lowerHalf
debug amount
pure ()
You might ask why we make the distinction between the two here. There isnāt a particularly strong reason, we just havenāt implemented support for bigger literals yet.
Thanks @cocreature !!
So does that mean that the statement in the docs cited above is incorrect? We are creating some training materials and need to make sure we define BigNumeric correctly.
Both statements above are correct. One applies to literals, i.e., the actual numbers in your source code. The other applies to all values of type BigNumeric
The docs do already make that distinction
OK, so we can make a BigNumeric by using smaller values that are within Numeric range, e.g., something like this:
let lowerHalf = 1.0 : BigNumeric
let upperHalf = 1.0 : BigNumeric
let amount = upperHalf * 1e37 * 1e37 * 1e37 + lowerHalf * 1e-37 * 1e-37 * 1e-37 * 1e-37
debug amount
i can keep increasing the upper and lower sides by multiplying with 1e37. As soon as I make it 1e38, it breaks.
Thank you, @Neelam_Dwivedi, for initiating a great discussion.
I took up your implied challenge of generating a really wide BigNumeric.
Using daml repl
ā¦
daml> let big = (foldl (\b _ -> b * 1e32 : BigNumeric) 1.0 [1..1023]) * 1e31
daml> let small = (foldl (\s _ -> s * 1e-32 : BigNumeric) 0.1 [1..1023]) * 1e-31
daml> let wide = big + small
daml> import DA.Text qualified as T (length)
daml> T.length(show wide)
65537
daml> 2^15 + 2^15 + 1
65537
2^15 whole digits + 2^15 fractional digits + 1 decimal point = 65537 characters
2 Likes
Awesome work @WallaceKelly ā¦ a great exercise to challenge some learners in our future training programs! Thank you!