# Error for 396^n

**URL:** <https://discourse.julialang.org/t/error-for-396-n/110099>\
**Category:** General Usage\
**Tags:** bug, error\
**Created:** [February 12, 2024, 12:22pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099 "2024-02-12T12:22:51Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jeroens](https://avatars.discourse-cdn.com/v4/letter/j/ac91a4/32.png) [@Jeroens](https://discourse.julialang.org/u/Jeroens)\
**Post date:** [February 12, 2024, 12:22pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/1 "2024-02-12T12:22:51Z")

</div>

Something weird is happening in Julia when using 396^8…  
In fact 396^n with n \< 8 works fine, with n =\>8 gives you a large negative number…

---

<div class="post-metadata">

**Author:** ![Dan](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/dan/32/42581_2.png) [@Dan](https://discourse.julialang.org/u/Dan)\
**Post date:** [February 12, 2024, 12:29pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/2 "2024-02-12T12:29:45Z")

</div>

This is because Int64 type overflows in some calculations, leading to mathematically incorrect results (including negative numbers).  
Julia chose to use Int64 and to overflow silently because of performance considerations.  
Two ways to get around this problem are:

1. choose an appropriate bigger datatype such as Int128 or BigInt.
2. use safe operation at the cost of performance. Safe operations can be used with the help of SaferIntegers package.

For example:

```julia
julia> BigInt(396)^8
604729962940281716736

julia> Int128(396)^8
604729962940281716736

```

and

```julia
julia> using SaferIntegers

julia> SafeInt64(396)^8
ERROR: OverflowError: 396^8

```

---

<div class="post-metadata">

**Author:** ![fabiangans](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/fabiangans/32/2624_2.png) [@fabiangans](https://discourse.julialang.org/u/fabiangans)\
**Post date:** [February 12, 2024, 12:55pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/3 "2024-02-12T12:55:55Z")

</div>

And note that Julia is not alone in this behavior, for example in python you would get:

```python
>>> import numpy as np
>>> np.power(396,np.arange(1,10))
array([ 396, 156816, 62099136,
                24591257856, 9738138110976, 3856302691946496,
        1527095866010812416, -4012591492133486592, -2566240545839251456])

```

---

<div class="post-metadata">

**Author:** ![baggepinnen](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/baggepinnen/32/693_2.png) [@baggepinnen](https://discourse.julialang.org/u/baggepinnen)\
**Post date:** [February 12, 2024, 12:59pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/4 "2024-02-12T12:59:03Z")

</div>

You’ll find relevant documentation under “Overflow behavior”  
[https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#Overflow-behavior](https://docs.julialang.org/en/v1/manual/integers-and-floating-point-numbers/#Overflow-behavior)

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [February 12, 2024, 12:59pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/5 "2024-02-12T12:59:51Z")

</div>

The power ^ operator is the one thing I would want to change in Julia, even power of 3 can be a problem, see linked issue. For a^b it’s rather unsafe, unless a and/or b are floating point numbers, or `big` integers, not even Int128 type is safe.

All math operators can overflow, even + (and \* and -), except /, and this may come as a surprise, except to users of most languages, such as C and C++, i.e. fast languages.

```julia
julia> typemax(Int128)+1
-170141183460469231731687303715884105728

```

In some sense that IS a correct result, i.e. ALL operators (expect `/` since it divides with a Float64 result) return modular math results, and they are correct when defined that way, but unexpected definition for many or most users. And for power, I think maybe never a good definition, while ok when you do not actually overflow, as with all the other operators.

So why do I only want to change `^`? Because the problem is more apparent there (it’s the one operator that is really dangerous, much more than the other), and with Int64 type (the default Int type on 64-platforms), +, -, are in practice not a worry, and \* also rarely, though more often.

[If you divide by 2, you get the correct _exact_ result at least half the time, but if you divide by e.g. 3, you _never_ get the correct _exact_ result, unless you use `Rational`s, and that is a problem for any language (except maybe Raku/Perl 6 that may default to rationals, or does it not?). And even the rationals need to be of the BigInt type to guard against overflow. So with math you are screwed in pretty much any language, unless you opt into non-defaults, take care. Why do I mention thi? Because correct math vs fast math is a trade-off in any language, even a trade-off between approximately correct and fast.]

> [@The speed of light is an integer. Why should we care?](https://discourse.julialang.org/t/the-speed-of-light-is-an-integer-why-should-we-care/40108/7):
>
> It is an unfortunate trade-off between performance and safety. However, I think that the decision to default to fast integers in Julia is correct, most of the time there is no overflow risk. However, it would be great if future CPUs would have hardware-support for zero-cost overflow safe integers.

---

<div class="post-metadata">

**Author:** ![heliosdrm](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/heliosdrm/32/3851_2.png) [@heliosdrm](https://discourse.julialang.org/u/heliosdrm)\
**Post date:** [February 12, 2024, 1:00pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/6 "2024-02-12T13:00:32Z")

</div>

And the answer to “why” in the [Frequently Asked Questions · The Julia Language](https://docs.julialang.org/en/v1/manual/faq/#faq-integer-arithmetic)

[https://docs.julialang.org/en/v1/manual/faq/#faq-integer-arithmetic](https://docs.julialang.org/en/v1/manual/faq/#faq-integer-arithmetic)

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [February 12, 2024, 1:30pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/7 "2024-02-12T13:30:24Z")

</div>

What you CAN do (without adding a package) is this and similar for all the operators except `pow` (in 1.10, it seems to be there already in 1.11, and ~~can~~ also be used in older Julia versions with Compat.jl, not yet, but hypothetically in a future version of it):

julia\> Base.Checked.checked\_mul(396, 8)  
3168

> help?\> Base.Checked.checked\_div(396, 8)  
> Base.checked\_div(x, y)
> 
> Calculates div(x,y), checking for overflow errors where applicable.
> 
> The overflow protection may impose a perceptible performance penalty.

but there’s actual no extra penalty over `div` (and some other related) since I checked:

> julia\> @edit Base.Checked.checked\_div(396, 8)
> 
> checked\_div(x::T, y::T) where {T\<:Integer} = div(x, y) # Base.div already checks

This is intriguing, because div(a, b) can’t overflow for any positive b (e.g. never if it’s an Unsigned type), and only in rare cases like produces an error, only for typemin I think:

> julia\> div(typemin(Int64), -1)  
> ERROR: DivideError: integer division error

I know there’s an issue about making ^ checked by default. I want such available for sure, as for other operators (maybe I overlooked it, and it’s already available as I thought), and I would rather argue for Float64 result (same as with division, and for the _same_ reason), rather than checked by default, though that is also a valid choice.

The problem with checked by default is that, while ^ is most dangerous, you could argue for checked by default for all (or none), and it is a bit of an inconsistency to only check one operator. In general a^b implies division if b is negative, so that’s why I rather want Float64 result for _more_ consistency.

FYI: Unrelated, or not, and looking up I found this I did NOT know of: [Collections and Data Structures · The Julia Language](https://docs.julialang.org/en/v1/base/collections/#Base.checked_length)

> `Base.checked_length(r)`
> 
> Calculates `length(r)`, but may check for overflow errors where applicable when […]

---

<div class="post-metadata">

**Author:** ![Palli](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/palli/32/3380_2.png) [@Palli](https://discourse.julialang.org/u/Palli)\
**Post date:** [February 12, 2024, 10:41pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/8 "2024-02-12T22:41:47Z")

</div>

FYI: It’s been discussed to change this to check (but only for `^`; for now), but it was closed recently, considered inconsistent for just one operator:

> <https://github.com/JuliaLang/julia/pull/21600>
>
> I haven't updated the tests yet, mostly because we need to get a consensus on wh…at to do.
> The thinking behind this is that by far the most common case of people running into overflows is trying to do things like \`10^x\`, when they meant \`10.0^x\`. Since this functionality is very well isolated, we can add checking without generally killing performance. There's a couple of details to work out though:
> \- What to do about small powers ^2, ^3, etc. @StefanKarpinski expressed a preference for those to keep behaving like \`x\*x\`, \`x\*x\*x\`.
> \- What to do about literals. Do we keep referential transparency (e.g. do the literal ^2, ^3 no check for overflow, but the non-literal one does).
> \- Are we ok with this? Initial performance numbers look like about a 10-20% performance penalty for this change.
> 
> cc @JeffBezanson @StefanKarpinski @stevengj @timholy

I’ve suggested starting work on Julia 2.0, and I still believe that should be done, maybe even just to change a few things such `^` behaviour, and that issue was also closed (for now, maybe time to reconsider that?), moved to a discussion:

> **[Start work on Julia 2.0, with it off by default, enablable with an ENV var ·...](https://github.com/JuliaLang/julia/discussions/50836)**
>
> There are a number of breaking Julia 2.0 issues (see the milestone) that I would want implemented, but I would also want all the code that works in 2.0 to also work in 1.x. I think we're actually g...

---

<div class="post-metadata">

**Author:** ![jar1](https://avatars.discourse-cdn.com/v4/letter/j/c0e974/32.png) [@jar1](https://discourse.julialang.org/u/jar1)\
**Post date:** [February 12, 2024, 11:08pm UTC](https://discourse.julialang.org/t/error-for-396-n/110099/9 "2024-02-12T23:08:19Z")

</div>

Numpy uses machine integers. Python itself uses big integers

```julia
In [2]: [396 ** n for n in range(10)]
Out[2]: 
[
    1,
    396,
    156816,
    62099136,
    24591257856,
    9738138110976,
    3856302691946496,
    1527095866010812416,
    604729962940281716736,
    239473065324351559827456,
]

```
