-
Notifications
You must be signed in to change notification settings - Fork 137
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
percent_t FROM double and TO double are different #301
Comments
I saw old closed tickets where Nick (thanks to him for this great job) says the way percent_t works is by design, but I disagree, this is simply inconsistency. |
You're not wrong. I recently wrestled with trying to make this consistent in v3.x and started seeing all the warts in concentration units. I think that the problem goes back to the fact that "dimensionless" units really lack context for conversions, and so unlike the rest of the dimensioned units it's not possible to squeeze out all the features while still being compatible with a double conversion. So in your example, you're totally right, one would expect identity. But consider this case:
The result should be None of this is to say that it shouldn't be different, that's just the background, but I've yet to find a solution to the consistency issue that didn't just move the problem and break something else. It's an active area of work but I'm not sure it can be solved without dimensioning dimensionless units (which could be done - but it's a can of worms especially when it comes to angles and physics) |
I wonder whether there actually can be a general scalable solution. I think the solution that has the least potential for confusion in this situation is to have custom functions to conversion to/from built-in types (for example, I'd guess similar concerns would also apply to the other types in |
Related issues:
I think the root problem is that the notion of the "value" of a quantity is dangerously ambiguous exactly when we have a dimensionless quantity with a magnitude other than 1. I discussed this a little bit in this comment: #275 (comment) I think the upshot is that these units can't have implicit conversions, in either direction. When we initialize a percent quantity by assigning |
My initial issue was not to set a value of 1 to a percent should result in 1% or 100%, but assigning a double to a percent then getting back this double front the percent should give the original double value.
13 janv. 2023 05:18:03 Chip Hogg ***@***.***>:
Related issues:
* > #81[#81]
* > #275[#275] (tangentially)
* > #276[#276], which I think this present issue technically duplicates?
…
I think the root problem is that the notion of the "value" of a quantity is dangerously ambiguous /exactly when/ we have a dimensionless quantity with a magnitude other than 1. I discussed this a little bit in this comment: #275 (comment)[#275 (comment)]
I think the upshot is that these units can't have implicit conversions, in either direction. When we initialize a percent quantity by assigning *1.0* to it, either 100% or 1% are perfectly reasonable answers. Asking "which one is right" is a recipe for confusion. Instead, save implicit conversions for the cases where an unambiguous correct answer exists.
—
Reply to this email directly, view it on GitHub[#301 (comment)], or unsubscribe[https://github.com/notifications/unsubscribe-auth/ABPAFIANARKSF6EPH7OS273WSDJM7ANCNFSM6AAAAAASLFR3JA].
You are receiving this because you authored the thread.[Image de pistage][https://github.com/notifications/beacon/ABPAFIGBATE3TVIIDXWSAULWSDJM7A5CNFSM6AAAAAASLFR3JCWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTSSKTWFG.gif]
|
Sorry, I had a hard time understanding the point you were trying to get across. Was it...
I was going to respond, but I wanted to make sure I wasn't talking past you. 🙂 |
My problem is the second sentence:
I don't care whether assigning 1.0 to percent_t gives 1% or 100%; I just care that it returns 1.0 when I assign it back to a double
In other words :
double d = 1.0;
percent_t p = d;
double d2 = p;
d2 should be equal to d ...
13 janv. 2023 13:32:29 Chip Hogg ***@***.***>:
My initial issue was not to set a value of 1 to a percent should result in 1% or 100%, but assigning a double to a percent then getting back this double front the percent should give the original double value.
Sorry, I had a hard time understanding the point you were trying to get across. Was it...
* > ..."#301[#301] does not duplicate #276[#276]"?
* > ..."I don't care whether assigning *1.0* to *percent_t* gives 1% or 100%; I just care that it returns *1.0* when I assign it back to a *double*"?
* > ...something else?
…
I was going to respond, but I wanted to make sure I wasn't talking past you. 🙂
—
Reply to this email directly, view it on GitHub[#301 (comment)], or unsubscribe[https://github.com/notifications/unsubscribe-auth/ABPAFIBPBW4L3GQZPOK2UDTWSFDLDANCNFSM6AAAAAASLFR3JA].
You are receiving this because you authored the thread.[Image de pistage][https://github.com/notifications/beacon/ABPAFIB77ICTVGU6LJLK3P3WSFDLDA5CNFSM6AAAAAASLFR3JCWGG33NNVSW45C7OR4XAZNMJFZXG5LFINXW23LFNZ2KUY3PNVWWK3TUL5UWJTSSLRXPC.gif]
|
OK, thanks for clarifying! For d2 to equal d, then we must choose one of those two conventions, even if you personally don't care which we choose. Let's game it out. If we choose the "underlying value" convention (so that Therefore, we're left with the "scalar value" convention (so that percent_t p1 = 1.0; // 100%
percent_t p2{1.0}; // 1% This seems completely unworkable because it violates deeply held intuitions about how C++ types should behave. Thus, we've eliminated both options. The only workable solution I've ever seen to this problem is to disable the implicit constructors and conversion operators for precisely these units: dimensionless units other than "the unit 1". Implicit conversions never make sense unless an operation is completely unambiguous. But for these units, the operation is ambiguous. Therefore, we can rule out supporting implicit conversions. |
I do not see thinks like that.
Back to my example:
double d = 1.0;
percent_t p = d;
double d2 = p;
Could be modified a bit to be clearer:
double d, d2;
percent_t p;
d = 10.0;
p = d;
d2 = p;
Here, d and d2 should be equal: 10.0
I do not mix affectation with initialization, which are different thinks
for me. But I may be wrong ...
Look:
percent_t p1 = 1.0;
percent_t p2{1.0};
I could accept (and may be understand) that here, p1 and p2 are of
different values; But affectation IN and OUT should be consistent ...
But, I have to say, whatever the future decision about this detail is
(change something or not), I already found a workaround for my own usage
and I am fine with the library as is.
(sorry for English mistakes, I am a poor old Frenchie ...)
Thanks a lot for your attention
Patrice
Le sam. 14 janv. 2023 à 22:59, Chip Hogg ***@***.***> a
écrit :
… My problem is the second sentence:
I don't care whether assigning 1.0 to percent_t gives 1% or 100%; I just
care that it returns 1.0 when I assign it back to a double
In other words :
double d = 1.0;
percent_t p = d;
double d2 = p;
d2 should be equal to d ...
OK, thanks for clarifying!
For d2 to equal d, then we must choose one of those two conventions, even
if you personally don't care which we choose. Let's game it out.
If we choose the "underlying value" convention (so that 1.0 is equivalent
to 1%), then multiplying by percent_t{1.0} is the same as multiplying by
1.0. This is clearly wrong, so I think we can safely eliminate this
option.
Therefore, we're left with the "scalar value" convention (so that 1.0 is
equivalent to 100%). In order to make the round-trip consistent, we need to
make the assignment operator semantically different from the copy
constructor by a factor of 100:
percent_t p1 = 1.0; // 100%percent_t p2{1.0}; // 1%
This seems completely unworkable because it violates deeply held
intuitions about how C++ types should behave.
Thus, we've eliminated both options.
The only workable solution I've ever seen to this problem is to disable
the implicit constructors and conversion operators for precisely these
units: dimensionless units other than "the unit 1". Implicit conversions
never make sense unless an operation is completely unambiguous. But for
these units, the operation *is* ambiguous. Therefore, we can rule out
supporting implicit conversions.
—
Reply to this email directly, view it on GitHub
<#301 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/ABPAFIHS3BAJKJ5BFBU5I6DWSMOVPANCNFSM6AAAAAASLFR3JA>
.
You are receiving this because you authored the thread.Message ID:
***@***.***>
|
Implicit conversions to/from built-in types appear to be a potential source of confusion for dimensionless units with a scaling factor (e.g., percent<>) [0]. Disallowing implicit conversions in those cases might be a not-terrible way to eliminate this potential for confusion without decreasing usability. The idea for limiting the implicit conversion to unscaled values was adapted from mpusz/units [1]. I'm not entirely confident this implementation is the best approach, but it's at least not obviously broken. [0]: nholthaus#301 [1]: mpusz/mp-units#412 (comment)
Compiling on Linux with up-to-date version at bug date
Consider this code:
double d50 = 50.0;
percent_t p50 = d50;
double d50_2 = p50;
Here, d50_2 value is 0.5, which is a problem.
If assigning a double to a percent_t considers the double holds PERCENT, then the oposite operation percent_t assigned to double should give PERCENT and not absolute value.
Am I wrong?
The text was updated successfully, but these errors were encountered: