Search code examples
mathgroovynumberformatexceptionbignum

Groovy throws Numberformatexception when dealing with extremely large numbers


So using groovy in Intellij IDEA, I get an exception using the following code:

def t = (100000G**100000000000G)

Now I'm aware these are numbers that no sane human being would ever want to compute, but for the purpose of asking and due to my curiosity, why does this throw the following exception?

Exception in thread "main" java.lang.NumberFormatException
at java.math.BigDecimal.<init>(BigDecimal.java:494)
at java.math.BigDecimal.<init>(BigDecimal.java:383)
at java.math.BigDecimal.<init>(BigDecimal.java:806)
at java.math.BigDecimal.valueOf(BigDecimal.java:1274)
at org.codehaus.groovy.runtime.DefaultGroovyMethods.power(DefaultGroovyMethods.java:14303)
at org.codehaus.groovy.runtime.dgm$489.invoke(Unknown Source)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite$PojoMetaMethodSiteNoUnwrapNoCoerce.invoke(PojoMetaMethodSite.java:274)
at org.codehaus.groovy.runtime.callsite.PojoMetaMethodSite.call(PojoMetaMethodSite.java:56)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:47)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:116)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:128)
at dev.folling.code.Main.main(Main.groovy:11)

Replacing ** with .power() doesn't change anything about it. The error is apparently caused due to an illegal character showing up at some point. I supsect it might be a memory error though I'm not sure.


Solution

  • You can try make a break point for your code, and try to dig into it.

    This is what will happen under the hood.

    public static BigInteger power(BigInteger self, BigInteger exponent) {
        return exponent.signum() >= 0 && exponent.compareTo(BI_INT_MAX) <= 0?self.pow(exponent.intValue()):BigDecimal.valueOf(Math.pow(self.doubleValue(), exponent.doubleValue())).toBigInteger();
    }
    

    Inside the running process, it get "Infinity" back as a return with the following code:

    Math.pow(self.doubleValue(), exponent.doubleValue())
    

    Then BigDecimal will use valueof to transform it to a BigInteger

    BigDecimal.valueOf("Infinity")
    

    This is why you will get a NumberFormatException

    Br,

    Tim