Saggi Posted December 20, 2019 Share Posted December 20, 2019 Hello all, Noob here 😑. Need help in solving this task. I Wrote a function which returns a factorial number but how to pass the logic that the passing parameter must be an integer. Also, if any other data type is passed, function should return error “Please provide correct data type”. Many thanks, function fact ($x) { if($x <= 1) { return 1; } else { return $x * fact($x - 1); } } echo fact(3); Quote Link to comment Share on other sites More sharing options...
Barand Posted December 20, 2019 Share Posted December 20, 2019 (edited) ctype_digit() function fact ($x) { if (!ctype_digit("$x") ) { // CAVEAT: cast $x to string type return 'Please provide an integer'; } if($x <= 1) { return 1; } else { return $x * fact($x - 1); } } Edited December 20, 2019 by Barand caveat 1 Quote Link to comment Share on other sites More sharing options...
gw1500se Posted December 20, 2019 Share Posted December 20, 2019 Minor point. I think the check will catch negative integers since it is cast to a string but the error should say 'Please provide a positive integer". Quote Link to comment Share on other sites More sharing options...
Psycho Posted December 20, 2019 Share Posted December 20, 2019 FWIW, what the task to specifically create a recursive function? If not, you can get a factorial much simpler (of course you'd still want the integer check array_product(range(1, $number)); Quote Link to comment Share on other sites More sharing options...
benanamen Posted December 20, 2019 Share Posted December 20, 2019 (edited) Hi @Barand, I am wondering why you would be introducing strings when this is specifically about int's. IMO is_int should be used instead of ctype_digit. OP, the else is redundant. You can remove it. Additionally, IMO the int check should not be in the function. The function/method should do one thing and do it well. As is example function fact($x) { if (!is_int($x)) { return 'Please provide an integer'; } if ($x <= 1) { return 1; } return $x * fact($x - 1); } echo fact(5); Suggested Example function fact(int $x): int { return $x <= 1 ? 1 : $x * fact($x - 1); } $x = 5; echo is_int($x) ? fact($x) : 'Please provide an integer'; Edited December 20, 2019 by benanamen Quote Link to comment Share on other sites More sharing options...
Barand Posted December 20, 2019 Share Posted December 20, 2019 Yep, more than one way to skin a cat. Quote Link to comment Share on other sites More sharing options...
Psycho Posted December 20, 2019 Share Posted December 20, 2019 1 hour ago, benanamen said: I am wondering why you would be introducing strings when this is specifically about int's. IMO is_int should be used instead of ctype_digit. The OP never stated "where" the value is coming from. If the value is coming from a POST/GET variable it will ALWAYS be a string and always fail the is_int() test - even if the value is something like "5". If the value is specifically cast as an integer then there would be no reason to even test if it is an integer to begin with. So, it would only make sense to test if the value "looks" like an integer when it is an unknown string value that can be a string representation of an integer or some other invalid value. @Barand's test makes more sense. Quote Link to comment Share on other sites More sharing options...
benanamen Posted December 20, 2019 Share Posted December 20, 2019 (edited) 2 hours ago, Psycho said: The OP never stated "where" the value is coming from. Which is why you cant say "@Barand's test makes more sense." Based on OP's code, he expects there could be a negative int, otherwise he wouldn't be checking for it. If "int" is negative, @Barands solution will fail (false). var_dump(ctype_digit('-128')); // False Casting the string to an int wouldn't work either. $x = (int) '5'; Yes , it will make it an int and support negative values, but it will cast "anything" you put in there into an int such as the following and then you cannot check if it is a real int. $x = (int) 'xx'; // int 0 So what to do then? One option that also addresses the source as a string argument would be the following. function fact($x): int { return $x <= 1 ? 1 : $x * fact($x - 1); } $x = '-2147483648';// OK $x = -2147483648;// OK $x = 5; // OK $x = '5';// OK $x = 'ABC'; // Fail: Please provide an integer echo (filter_var($x, FILTER_VALIDATE_INT) === 0 || filter_var($x, FILTER_VALIDATE_INT)) ? fact($x) : 'Please provide an integer'; Edited December 20, 2019 by benanamen Quote Link to comment Share on other sites More sharing options...
Psycho Posted December 23, 2019 Share Posted December 23, 2019 On 12/20/2019 at 3:37 PM, benanamen said: Which is why you cant say "@Barand's test makes more sense." Based on OP's code, he expects there could be a negative int, otherwise he wouldn't be checking for it. If "int" is negative, @Barands solution will fail (false). If the value is a negative integer - it should fail. Factorials of negative numbers is not possible (e.g. division by zero) - unless you want to get into abstract complex numbers which would require the use of the gamma function. The only valid values for a factorial are positive integers from zero to ∞. The only exception I can think of to the ctype_digit() test would be if you wanted to allow a plus symbol; in which case you would still need to remove it during the computation. Quote Link to comment Share on other sites More sharing options...
benanamen Posted December 23, 2019 Share Posted December 23, 2019 1 hour ago, Psycho said: Factorials of negative numbers is not possible Thanks @Psycho. Shows how much I knew about Factorials, lol. Quote Link to comment Share on other sites More sharing options...
Barand Posted December 23, 2019 Share Posted December 23, 2019 On 12/20/2019 at 9:37 PM, benanamen said: Based on OP's code, he expects there could be a negative int, otherwise he wouldn't be checking for it. He's testing for 0 or 1. 0! and 1! both equate to 1, so no need to calculate any further. Every recursive function needs a stop condition otherwise you quickly overflow the stack with an infinite recursion. 1 Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.