# Factorial program

**URL:** <https://discourse.julialang.org/t/factorial-program/123010>\
**Category:** New to Julia\
**Created:** [November 24, 2024, 9:52am UTC](https://discourse.julialang.org/t/factorial-program/123010 "2024-11-24T09:52:37Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![hack3rcon](https://avatars.discourse-cdn.com/v4/letter/h/96bed5/32.png) [@hack3rcon](https://discourse.julialang.org/u/hack3rcon)\
**Post date:** [November 24, 2024, 9:52am UTC](https://discourse.julialang.org/t/factorial-program/123010/1 "2024-11-24T09:52:38Z")

</div>

Hello,  
I know that Julia has a function called `factorial`. I have written a program as follows to do this:

```julia
function fact(a)
    F = 1
    for n = 1 : (a - 1)
        F = F * (n + 1)
        println(F)
    end
end

```

Is it OK?

Thank you.

---

<div class="post-metadata">

**Author:** ![abraemer](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/abraemer/32/51403_2.png) [@abraemer](https://discourse.julialang.org/u/abraemer)\
**Post date:** [November 24, 2024, 10:39am UTC](https://discourse.julialang.org/t/factorial-program/123010/2 "2024-11-24T10:39:53Z")

</div>

> [@hack3rcon](#):
>
> Is it OK?

In what sense? What do you want to achieve? What should be critiqued?  
A couple of things I notice:

- typically variable names start with a lowercase letter and only typenames are capitalized
- your function does not return the value but only prints it to stdout
- his function always returns an `Int64`. You could consider to use the type of the argument to perform the computation

---

<div class="post-metadata">

**Author:** ![stevengj](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevengj/32/71_2.png) [@stevengj](https://discourse.julialang.org/u/stevengj)\
**Post date:** [November 24, 2024, 12:05pm UTC](https://discourse.julialang.org/t/factorial-program/123010/3 "2024-11-24T12:05:38Z")

</div>

> [@abraemer](#):
>
> In what sense? What do you want to achieve? What should be critiqued?

From @hack3rcon’s previous post ([Questions about a starting language, is Julia good (enough)](https://discourse.julialang.org/t/questions-about-a-starting-language-is-julia-good-enough/119731/)), they are just learning how to program for the first time and want pedagogical feedback.

---

<div class="post-metadata">

**Author:** ![StevenSiew](https://sea2.discourse-cdn.com/julialang/user_avatar/discourse.julialang.org/stevensiew/32/218393_2.png) [@StevenSiew](https://discourse.julialang.org/u/StevenSiew)\
**Post date:** [November 25, 2024, 2:53am UTC](https://discourse.julialang.org/t/factorial-program/123010/4 "2024-11-25T02:53:06Z")

</div>

> [@stevengj](#):
>
> From @hack3rcon’s previous post ([Questions about a starting language, is Julia good (enough)](https://discourse.julialang.org/t/questions-about-a-starting-language-is-julia-good-enough/119731/)), they are just learning how to program for the first time and want pedagogical feedback.

For beginners

1. Use BigInt
2. use return
3. print out the result outside of the function

```julia
function myfactorial(n)
    result = big(1)
    for i = 1:n
       result *= i
   end
   return result
end

println("factorial(13) = $(myfactorial(13))")

```

Advantages of BigInt  
Always return the correct result

Disadvantages of BigInt  
very SLOW

Why not use Int64 instead  
Because at certain input values, the Int64 result will be incorrect due to overflow error. Beginners need to learn Integer overflow error due to the physical structure of how a computer stores the value of Int64

Will BigInt always return the correct answer?  
No, at certain point, even BigInt will fail.

```julia
julia> myfactorial( parse(BigInt,"9999999999999999999999999999999999999999999999999999999999999999999999999999999") )

```

---

<div class="post-metadata">

**Author:** ![Benny](https://avatars.discourse-cdn.com/v4/letter/b/49beb7/32.png) [@Benny](https://discourse.julialang.org/u/Benny)\
**Post date:** [November 25, 2024, 6:55am UTC](https://discourse.julialang.org/t/factorial-program/123010/5 "2024-11-25T06:55:22Z")

</div>

> [@hack3rcon](#):
>
> Is it OK?

It’s a clear for loop in a concise method, keep doing that in general. What’s worth working on is the starting value; others have mentioned it, but I have more thoughts on it. `F=1` starts with a `Int64`. The type of the elements `n = 1 : (a-1)` will depend on `a`, so the type of `F = F * (n + 1)` also depends on `a` (for example, try `fact(5.0)`). When a variable changes its runtime type, it’s called type instability. It’s not wrong, exactly, because Julia allows it by design, but there are performance and correctness benefits to type stability so thinking about how types might change is a good habit. If you want to work with generic types and accept the overflow issues, you could replace `1` with `one(a)`. Otherwise I’d unconditionally start with `BigInt` like StevenSiew suggests, and I’d additionally limit the argument `myfactorial(n::Integer)` so we don’t unnecessarily involve other numerical types like `BigFloat`.

Now I’d like to talk about what base Julia does, just for context on how factorial functions could be implemented. Julia has a `factorial(n::Integer)` method that uses a for-loop starting at a generic type, but that method is not actually used by base integer types. Most of the other methods taking the base integer types check lookup tables with all the precomputed values that don’t overflow, and otherwise throws an error informing you of the need for a higher capacity type. If you don’t want to expend the memory for lookup tables, you can at least precompute the minimum `a` to overflow a particular type and throw an error when users try to exceed it. The `factorial(n::BigInt)` and `factorial(n::BigFloat)` methods wrap the corresponding functions in the GMP and MPFR libraries, which I don’t know anything about.

Note that you are computing a product of a sequence starting with one, possibly with a generic type. That is exactly what the `prod(itr; [init])` method does, only it exposes the starting point and the sequence (and thus their types) to the call. So, an equivalent to StevenSiew’s `myfactorial(5)` would be `prod(1:5; init = big(1))`. The starting point is optional and defaults to the sequence’s start, so ` prod(1:5; init=1) == prod(1:5)`. The advantage of `prod` is that a fraction of factorials is often used to express a product of an integer sequence, e.g. the permutation formula n!/(n-r)! is expressing `prod(n-r+1:n)`, and it saves far more time and is far less prone to overflow than `factorial(n)÷factorial(n-r)`.
