-
Notifications
You must be signed in to change notification settings - Fork 473
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
floordiv (and divmod, modulo, math.floor) raise DimensionalityError #943
Comments
You are correct. Please submit a PR |
Got it. I'm not sure when I will have time for this.
In the meantumey, is there a workaround? I tried dividing by ureg(3) and
Quantity(3) but didn't have any luck.
…On Sat, Dec 21, 2019, 12:21 AM Hernan Grecco ***@***.***> wrote:
You are correct. Please submit a PR
—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub
<#943?email_source=notifications&email_token=AAAMNS3MPWIOZEX5OGRBLSTQZWRXNA5CNFSM4J6AO652YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOEHOVODQ#issuecomment-568153870>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAAMNS6UGQMZMDHQL4NYXOTQZWRXNANCNFSM4J6AO65Q>
.
|
I am phasing this to 0.11 |
Good that I came here before the PR got merged.... This issue is blatantly wrong. Floordiv should absolutetly give a DimensionalityError, because it is a dimensionality error. Your example shows this very well. You want to floor-divide 10" by 3. What in world should the result be? Probably you say 3". But this is exactly the dimensionality error that pint tries heavily to prevent you from. Why? Because I guess we agree that 10" = 254 mm. If you floor-divide that by 3 in your logic, you get 84 mm, which is certainly not the 3" you got from before. You could argue now so what, apparently floor division does not make sense for united values. But also this is not true. It makes a lot of sense: imagine you have a log of 1 m, and want to cut it in 1" pieces. Then you calculate 1 m // 1 " and voilà, you get a nice 39, which is true whatever unit you convert it to, simply because it actually corresponds to a real-world problem. All the same applies for modulo. In the end, we should fulfill the Python documentation (see https://docs.python.org/3/library/functions.html#divmod). Let q = a // b:
This quote is also well-defined if there are units involved. And the current implementation does fulfill this rule (hopefully there are no bugs...) |
There should be a way to Could that be done in a context manager that sets e.g. a thread local flag to not raise because the user is explicitly asking to modulo and preserve the unit? |
Use case: I have 10ft of 2x4; how many 4ft sections can I make out of that? Could you show how to drop the unit, perform modulo division, and re-apply the unit? |
Your use case is exactly the use case that works (or at least should work, provided there is no bug). On my machine, latest pint:
that says: if you have a log of 10 ft length and want to chop 4 ft pieces, you get 2 pieces and are left over with 2 ft of wood. In my example above I even do that with mixed units, like this:
meaning: if you have a log of 1 m length and want to chop it into footlongs, you get 3 foot-long pieces and 85.6 mm left over. I have no idea what the result of |
What is the status of this issue which I discovered when I was about to open a similar issue, but maybe it better fits as a comment here. from pint import UnitRegistry
ureg = UnitRegistry()
parse = ureg.parse_expression
# The following should both rather return 1 meter, but return 10 meter.
print(parse("5 m % 2"))
print(parse("(5 % 2) m"))
# The following should both rather return 2 meter, but return 10 meter.
print(parse("5 m // 2"))
print(parse("(5 // 2) m"))
# The following raise a somewhat misleading errors:
# 5 * ureg.m // 2
# DimensionalityError: Cannot convert from 'meter' to 'dimensionless'
# 5 * ureg.m % 2
# DimensionalityError: Cannot convert from 'dimensionless' (dimensionless) to 'meter' ([length]) |
Thanks for the feedback @deeplook. I can reproduce, it seems binary opertors for floordiv & mod operators are missing in the token evaluator. After adding them we get the proper results. >>> from pint import UnitRegistry
>>>
>>> ureg = UnitRegistry()
>>> parse = ureg.parse_expression
>>> parse("5 m % 2")
pint.errors.DimensionalityError: Cannot convert from 'dimensionless' (dimensionless) to 'meter' ([length])
>>> parse("(5 % 2) m")
<Quantity(1, 'meter')>
>>> parse("5 m // 2")
pint.errors.DimensionalityError: Cannot convert from 'meter' to 'dimensionless'
>>> parse("(5 // 2) m")
<Quantity(2, 'meter')> I'll make a PR for this. |
While I am not sure about the missing operators, I can only say that in the example that you give a In short: for floordiv and modulo both operands need to have the same dimensions, like for addition or subtraction, otherwise it makes no sense. |
It works as expected with the new version. #1471 >>> parse("5 m % (2 m)")
<Quantity(1, 'meter')>
>>> parse("5 m // (2 m)")
<Quantity(2, 'dimensionless')> It only works with the parentheses around 2 m though. Don't know if thats a side effect of the parser.
|
When something makes no sense there is the option to define some sense. So one could regard |
Well, if you regard it like that, what should the value of |
You would stick with the one unit you have, and get a 0 result. Again, I'm not dogmatic on it. Either way it might cause surprises, so let's pick the one closest to the Python conventions. |
I think this is fixed. Feel free to reopen. |
This one is wrong, too, FWIU: hgrecco/pint-pandas#95 (comment) :
|
What could a better Exception message read? |
I don't agree with some of the conclusions in this thread because they are predicated on the idea that all operations should be unit-aware. Specifically this statement:
If you accept the above argument, then However, I do agree that
|
Well, if floor is unit-agnostic, as you say, can you please tell me what is |
That doesn't really have anything to do with |
Sure. But for your presumably unit-agnostic mathematical function, what is |
Maybe this is more about standardization? After all, units are given by physists, say, with different cultural backgrounds before eventually some standardization emerges, if it does. So one could argue that That said, I kind of dislike that |
Well, in engineering, the standard base unit is certainly the millimeter. Why not that? And for mass, should the standard base unit be kilogram, or gram? And why? What about the volume, cubic meter, or better liter? Note that |
The answer is in my comment.
I agree that this is a separate issue.
The proposed behavior of floor is the same for all of these because it just preserves the unit of its argument. |
floordiv (and divmod, modulo, math.floor) raise DimensionalityError, but I don't understand why because division by a dimensionless integer does not raise DimensionalityError?
Raises
DimensionalityError: Cannot convert from 'dimensionless' (dimensionless) to 'inch' ([length])
, which is what the tests say it should raise:pint/pint/testsuite/test_quantity.py
Lines 715 to 720 in 4c3114c
I could try and redefine floordiv and divmod to just use division and floor? But why is that necessary? That doesn't work either?
The text was updated successfully, but these errors were encountered: