BigNumeric error

    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.

exactly

1 Like

Thank you!!! :pray:

1 Like

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

:nerd_face:

2 Likes

Awesome work @WallaceKelly … a great exercise to challenge some learners in our future training programs! Thank you!