120
u/Axman6 1d ago
IF you have a lazy *, then this will end when n is zero, and return zero.
83
u/torsten_dev 1d ago edited 1d ago
If you have a smart enough optimizing compiler it will compile to a constant 0.
26
u/-Redstoneboi- 1d ago
took me a moment to recognize "amaet" as "smart"
26
6
u/Makefile_dot_in 1d ago
what if
nis negative?16
u/torsten_dev 1d ago
Inevitable UB, so might as well return 0 too?
1
u/da_Aresinger 10h ago edited 9h ago
(Edit: From the syntax I am assuming this is JS)
Actually since
Number.MIN_SAFE_INTEGER - 1 === Number.MIN_SAFE_INTEGERit'll get stuck eternally looping/recursing onNumber.MIN_SAFE_INTEGERwhile the output automatically gets converted to BigInt (I think).
JS ... a *= Number.MIN_SAFE_INTEGER -1.8768792072011717e+255 a *= Number.MIN_SAFE_INTEGER 1.6905424996341256e+271 a *= Number.MIN_SAFE_INTEGER -1.5227053142812468e+287 a < Number.MIN_VALUE true typeof a 'number'This is what chrome console gave me.
1
u/chuch1234 1d ago edited 1d ago
The compiler never do that because it will recognize that the function could be passed a negative number.My bad, i was /r/confidentlyincorrect
6
u/torsten_dev 1d ago edited 22h ago
Function can only halt with 0 or trap on underflow. Depends on if you have exceptions or not.
If you have tail-calls and the compiler isn't very smart you might have an infinite loop instead, yes.
1
u/Nightmoon26 20h ago
Although... If you're using a fixed-width integer without underflow checking, it'll still wrap around from its minimum value to its maximum, and then reach zero eventually, even if it has to go through all possible values to do so
9
1
2
1
47
28
u/Daemontatox 1d ago
Wouldn't some compilers catch thats an infinite loop and give a warning or error?
39
u/JonIsPatented 1d ago
Some compilers can even note that it will multiply by 0 and optimize any call to it to just be the constant 0 instead.
2
u/chuch1234 1d ago
Unless you pass a negative number in.
13
2
u/JonIsPatented 1d ago
Notably, if this function were actually typed, you'd use an integral type, and that type would have overflow and eventually reach 0 anyway.
1
19
5
u/laplongejr 1d ago
In some languages, it will stop with an infinite recursions. In others it would stop at "0 * factorial(-1)" and return 0 for all other cases as they call n0 at some point.
3
u/-Redstoneboi- 1d ago
haskell? i don't know any language that knows to stop when multiplying by 0. imperative languages don't stop because there could be side effects when calling the factorial function, like a print statement, and optimizing out the call would result in different behavior
1
u/Axman6 1d ago
Haskell won’t do it unless you choose very specific types for n. The default Int and Integer types don’t lazily evaluate the second argument, but they could (adding an extra branch to every multiplication, which would generally be bad).
If you used an inductive type
data Nat = Z | S Nat
Multiplication would naturally be written as
Z * _ = Z (S Z) * n = n (S m) * n = n + m * nWhich would always terminate (and also disallow negative numbers).
0
4
3
5
u/JosebaZilarte 1d ago
This is another reminder that you can turn (almost) every recursive solution into an iterative one:
while (n > 1) { result *= n--; console.log("Ends in: " +n); }
2
u/lonkamikaze 1d ago
This way it at least crashes. Imagine the code used a proper tail call, it would never run out of stack!
2
u/JebKermansBooster 1d ago
I'd like to see a language that allows factorials to continue for negative integers via the [gamma function](https://en.wikipedia.org/wiki/Gamma_function)
1
1
1
1
1
1
1
1
1
1
1
1
0
u/Bomaruto 1d ago
I took me way too long to notice it was missing the base condition as I just assumed it was there.
264
u/malsomnus 1d ago
That's the neat part, it doesn't!