FazBrowse GitHub Viewer | Trending |
URL:
| Home
Tools: [Download Repo ZIP]   [Original HTTPS Page]

gh-101410: Improve error messages in math module by CharlieZhao95 · Pull Request #101492 · python/cpython · GitHub

/ cpython Public

gh-101410: Improve error messages in math module - #101492

Closed
CharlieZhao95 wants to merge 12 commits into
python:mainfrom
CharlieZhao95:gh-101410/math_error_message
Closed

gh-101410: Improve error messages in math module#101492
CharlieZhao95 wants to merge 12 commits into
python:mainfrom
CharlieZhao95:gh-101410/math_error_message

Conversation

CharlieZhao95 commented Feb 1, 2023
edited by bedevere-bot
Loading

Copy link
Copy Markdown
Contributor

Make several math functions support custom error messages.
math.sqrt() and math.log() now provide more helpful error messages.

>>> import math
# before
>>> math.sqrt(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math domain error

# now
>>> math.sqrt(-1)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math.sqrt() expects a non-negative input, got '-1'.
See cmath.sqrt() for variation that supports complex numbers

>>> math.log(0)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math.log() expects a positive input, got '0'.

Comment thread Modules/mathmodule.c Outdated
"Return the square root of x.")
"Return the square root of x.",
"math.sqrt() expects a non-negative input, got '%R'.\n"
"See cmath.sqrt() for variation that supports complex numbers")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Perhaps an a before variation would be more correct? Or

See cmath.sqrt(), which also supports negative inputs. I don't know what's better - just a suggestion (:

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Perhaps an a before variation would be more correct? Or

See cmath.sqrt(), which also supports negative inputs. I don't know what's better - just a suggestion (:

Thanks! It seems reasonable to me to add a. Let's wait for others to reply. :)

Copy link
Copy Markdown
Contributor Author

I guess similar functions and macros can have the same changes (eg FUNC1A, FUNC2). I will continue my work after the initial review. :)

CharlieZhao95 marked this pull request as ready for review February 3, 2023 02:19
Comment thread Modules/mathmodule.c Outdated
Comment thread Modules/mathmodule.c
if (Py_IS_NAN(r) && !Py_IS_NAN(x)) {
PyErr_SetString(PyExc_ValueError,
"math domain error"); /* invalid arg */
PyErr_Format(PyExc_ValueError, err_msg, arg); /* invalid arg */

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Shouldn't same message be used below on the line 1076 as well (infinite r for finite input)? atanh(-1) is an example.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Shouldn't same message be used below on the line 1076 as well (infinite r for finite input)? atanh(-1) is an example.

I was wondering if there is a function that can have both input and output( NAN r for non-NAN x and infinite r for finite x).

If such a function exists, it may lead to confusing error messages, because one error message corresponds to two scenarios. I haven't thought of such a function yet, please suggest if it exists. :)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Same atanh :)

atanh(2) - for the 1st scenario and atanh(1) - for the second. I doubt it will be confusing if you raise instead something like ValueError("atanh expects an argument from (-1, -1), got %R"). I don't think it does make sense to have a different descriptions for pole errors (like atanh(1)). @mdickinson ?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

See 9c32ae0 from #102523.

serhiy-storchaka left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Would not be better to output the converted C double value x instead of the original Python object arg? The repr of the Python object can be arbitrary long, unlike to the string representation of C double. Also, there may be some errors introduced at converting Python object to C double, not visible from its repr. Although it is much more cumbersome.

serhiy-storchaka commented Sep 23, 2023
edited
Loading

Copy link
Copy Markdown
Member

For example, math.log10(Fraction(1, 10**400)) raises an exception, even if the argument is positive. On other hand math.sqrt(Fraction(-1, 10**400)) returns -0.0 even if the argument is negative. BTW, math.sqrt() returning negative zero can cause issues in formatted output.

Copy link
Copy Markdown
Contributor Author

Would not be better to output the converted C double value x instead of the original Python object arg?

Thanks for your suggestion! I forgot this PR while waiting for others to review it, and it’s time to pick it up :)

IMO, it is better to use the C double variable. The only drawback is that we will lose some floating point precision in error message. Does this confuse others? Perhaps this minor flaw is acceptable.

# Using double(%f), the default value is six decimal places.
>>> math.sqrt(-math.pi)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math.sqrt() expects a nonnegative input, got '-3.141593'.
See cmath.sqrt() for a variation that supports complex numbers
>>> math.pi
3.141592653589793

>>> math.sqrt(-0.00000001)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ValueError: math.sqrt() expects a nonnegative input, got '-0.000000'.
See cmath.sqrt() for a variation that supports complex numbers

AA-Turner commented Sep 26, 2023
edited
Loading

Copy link
Copy Markdown
Member
ValueError: math.sqrt() expects a nonnegative input, got '-3.141593'.

Perhaps just append ' (rounded)' to the end of the line?

A

Copy link
Copy Markdown
Member

In most cases functions in the module are 1-arg. I think that if we show the function domain (e.g. math.sqrt() expects a non-negative input.) - this will be more than enough.

Copy link
Copy Markdown
Member

Of course, the output should be more precise and consistent with Python representation, so do not use snprintf() or like. There are several ways to do this:

  1. Create a Python float object with PyFloat_FromDouble, then use %R format.
  2. Use PyOS_double_to_string() (as in the implementation of float.__repr__), then use %s format to insert it in the error message.

Before writing code, wait to see if other core developers (in particular @mdickinson and @tim-one) have something to say about this idea.

Copy link
Copy Markdown
Member

FYI, @CharlieZhao95, this branch has unresolved conflicts. Are you planing to finish this? If not, I'll open a pr, based on this work.

Copy link
Copy Markdown
Contributor Author

FYI, @CharlieZhao95, this branch has unresolved conflicts. Are you planing to finish this? If not, I'll open a pr, based on this work.

Thanks for reminding! BTW, is it time to continue this PR? Maybe we can make this PR simpler (remove got '%R' from the error message first)

picnixz left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Can you add tests for checking the new messages?

Comment thread Modules/mathmodule.c Outdated
Comment thread Modules/mathmodule.c Outdated
Comment thread Modules/mathmodule.c
return NULL;

num = loghelper(args[0], m_log);
num = loghelper(args[0], m_log, "math.log() expects a positive input, got '%R'.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

I don't think using quotes around numbers is relevant. For instance, if it's a custom class of a float that overrides __repr__, then you don't necessarily want to surround the __repr__ by quotes.

Suggested change
num = loghelper(args[0], m_log, "math.log() expects a positive input, got '%R'.");
num = loghelper(args[0], m_log, "math.log() expects a positive input, got %R.");

Comment thread Modules/mathmodule.c
/*[clinic end generated code: output=5425899a4d5d6acb input=08321262bae4f39b]*/
{
return loghelper(x, m_log2);
return loghelper(x, m_log2, "math.log2() expects a positive input, got '%R'.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Ditto.

Comment thread Modules/mathmodule.c
/*[clinic end generated code: output=be72a64617df9c6f input=b2469d02c6469e53]*/
{
return loghelper(x, m_log10);
return loghelper(x, m_log10, "math.log10() expects a positive input, got '%R'.");

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Choose a reason Spam Abuse Off Topic Outdated Duplicate Resolved Low Quality

Ditto

CharlieZhao95 and others added 3 commits July 22, 2024 15:43
…t2aQE.rst

Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>
Co-authored-by: Bénédikt Tran <10796600+picnixz@users.noreply.github.com>

Copy link
Copy Markdown
Contributor Author

Can you add tests for checking the new messages?

Sure :) I'm waiting for other core developers to reply. I will add tests after they finalize the solution.

Copy link
Copy Markdown
Member

This work continued in #124299

This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

8 participants


Back | FazBrowse Home | New Git URL