Skip to content

Limit loop to compute factorial to n<=170, for n>170 return Perl Inf#682

Merged
pstaabp merged 2 commits intoopenwebwork:PG-2.17from
taniwallach:factorial-fix
May 29, 2022
Merged

Limit loop to compute factorial to n<=170, for n>170 return Perl Inf#682
pstaabp merged 2 commits intoopenwebwork:PG-2.17from
taniwallach:factorial-fix

Conversation

@taniwallach
Copy link
Member

Fixes the issue from #675 by returning Perl Inf for any integer n>170, and using the current approach for integer values of n in [0,170]. That seems to be the consensus on the best patch for the problem itself. Non-integervalues will return the same error message as before.

as that would be the result of the calculation used for any such
n due to overflow of the Perl floating point data type.
Copy link
Member

@drgrice1 drgrice1 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good to me.

I certainly agree with @dpvc on recursive factorials. Always prefer a loop over recursion if that can be done. Recursion carries too much overhead.

my $n = shift; my $f = 1;
$self->Error("Factorial can only be taken of (non-negative) integers")
unless $n =~ m/^\d+$/;
return Inf if $n > 170;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm wondering if this should produce a MathObject Infinity rather than a Perl Inf. (My comment on the original discussion used Inf to make it work like the other ones in Alex's tests.)

I get error messages about Inf being a bareword for this line. I think it may need to be

Suggested change
return Inf if $n > 170;
return $self->Package("Infinity")->new() if $n > 170;

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried the proposed change now.

Even with that change putting 171! inside a n input box for a Formula results in the error message Can't convert an Infinity to a constant.

Compute( "171!" ); also triggers that error for either option of the return value for n>170 (and also when the prior version of the code is used).

As such, it seems to me that keep the return value as a Perl infinity (which it would have been in the past) is a more certain way of maintaining backwards compatibility, and saves on any overhead of creating an object here when it has no purpose in the end.

I do see a warning about the bareword from perl -C lib/Parser/UOP/factorial.pm but it does not seem to interfere when used inside pg.

However, if you still think the change is advisable, I will make it.

Copy link
Member

@dpvc dpvc May 26, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Even with that change putting 171! inside a n input box for a Formula results in the error message Can't convert an Infinity to a constant.

I am not able to reproduce that. It works correctly for me (reporting an entered value of infinity and that the value is incorrect. No error message is produced. The code that converts to a constant does handle Infinity MathObjects (but not perl Inf, though perhaps it should).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I upgraded my version of PG. The Docker container had a somewhat old version. Now it works properly. Sorry.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Note: Peter's PR had the recommended change in it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is now merged, so $self->Package("Infinity")->new() is not the return value of n>170.

@pstaabp
Copy link
Member

pstaabp commented May 26, 2022

This also seems like we should have a unit-test for this. I wrote a number of unit tests last summer and hoped to do more. Let me see if I can pull one together to add to this PR.

@pstaabp
Copy link
Member

pstaabp commented May 26, 2022

I just wrote a factorial unit test and added as a PR to your branch @taniwallach.

* Added a test for the factorial.

* FIX: clarified some of the language in the tests.
@taniwallach taniwallach requested a review from dpvc May 27, 2022 14:37
Copy link
Member

@dpvc dpvc left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good.

@pstaabp pstaabp merged commit 3cdcd9b into openwebwork:PG-2.17 May 29, 2022
@taniwallach taniwallach deleted the factorial-fix branch May 29, 2022 10:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants