[issue41598] Adding support for rounding modes to builtin round
marco_ocram added the comment: "- What would you expect round(2.675, ndigits=2, mode=ROUND_HALF_UP) to give? I strongly suspect that Marco would expect and want a result of 2.68. But if we follow the existing rules for round, it's going to give 2.67." Yes, that's right. And my second humble implementation do this but only if the number have a decimal part, i mean the binary approximation is managed only for numbers with decimal positions, not for binary distortion in huge numbers with a positive exponent for example. For my application is ok but not in general, in my fast opinion a possible solution could be translate all numbers in exponential decimal format and evaluate the last digit that have to be condidered as an approximation decimal digit before applying calculations, or some kind of calculations. This is the case for example of 0.4...9 - What would you expect round(2.712, ndigits=3, mode=ROUND_UP) to give? The binary float given by the literal 2.712 is just a touch larger than 2.712, so it should round up, giving 2.713. But again, I doubt that's what users will expect or want. Even worse, the rounding is not idempotent: the float 2.713 is again a little larger than Decimal("2.713"), so it rounds up again: so if we round the value 2.712 twice to 3 digits using ROUND_UP, we'll get 2.714. This is the case of 0.5...1 for example and agreee with all stated. With the solution proposed above in my opinion could be managed this case too, translating and working on decimal representation and using last digit as rounding digit and only for this. The user will have no more the possibility to use it as a significant digit to don't have the need to guess nothing. But pheraps this means work with strings as implemented in decimals? Sorry i don't know this, but i can guess. In the end, the problem is not simple but not impossible in my opinion, it's right that decimals are already implemented and someone could work using them if needed, i don't want to impose nothing and convince noone but it's really funny in my opinion the only built-in rounding in a cutting-edge language as Python give me the banking rounding that as an not so young :-( engineer i've learned about now and give me results the same Microsoft in documentation index as misleading. I's right as i've already stated in sums reduce the rounding error but as i've reported the more common rounding peoples have in mind is the half up rounding. These are only my considerations, the choice is your, more experienced in the field then me. -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: i think in your long post you have underlined among others: 1. in binary implementation of floats one bit was reserved to rounding; 2. this one bit is not enough to manage a correct rounding in a converted decimal base; my considerations: 3. someone i think had evaluated deciding rounding didn't worth more significative digits; 4. the only solution in general can be use more digits to manage rounding in decimal base, not only one but more (i should think better and experiment on how many); 5. the problem in general cannot be solved by an implementation of rounding but from a revision of the implementation of floats (i have solved pretty well my personal need but i'm speaking in general); 6. this is not really a weak impact i think, despite it's not impossible; 7. and last, i think the current implementation could derive from historical reasons when we worked on 8 bits machines, not 64 bits, and one bit was of worth, but i may be wrong. -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: @Vedran: I'm sorry about my "quick-and-dirty implementations". As i've already stated the problem's more deep i expect, despite the second half up rounding for my needs now (after your observation) work well. I've verified other languages have the same problem with floats operations and roundings. @Steven: "Are you satisfied that adding a rounding mode to the built-in `round` function is a better solution than a series of functions in the math module? If so, I will change the title to reflect that." I fully agree with the sentence and with all the content of your writings. I think the decimal module is excellent and can do an extraordinary work (as extraordinary i suppose was the work of its coders) but floats also are fine for common people use, i see only the rounding as main them problem. It's very unpleasant to round 2.8-1.3 half up and without tricks obtain a misleading results. I think working on the last decimal digit if all are used the problem could be solved, but with a lot of study (at least for me if i have) cause one purpose have to be maintain good performances in addition to results always corrects. This is only a possibility to improve the core language, i think one function with more common rounding ways, as in wikipedia (in gnu c i don't see just "to nearest, ties away from zero" or half up we discuss) or in decimals module, can be useful to reduce the need of individual coders implementation on a not so simple question cause them needs not satisfied by the round() as banking rounding. -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: rndup is not correct and rnd work smooth only for numbers about < e16 until they have a fractional part. it's interesting but not simple. -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: thank you very much about the hints, i've improved the code as follows. def rnd(x, n=0): a = x*10**(n + 1) b = int(a) if abs(a - b) >= 0.5: b += 1 if x >= 0 else -1 a = b/10 b = int(a) if abs(a - b) >= 0.5: b += 1 if x >= 0 else -1 return b/10**n def rndup(x, n=0): a = x*10**(n + 1) b = int(a) if abs(a - b) > 0: b += 1 if x >= 0 else -1 a = b/10 b = int(a) if abs(a - b) > 0: b += 1 if x >= 0 else -1 return b/10**n now it manage well your cases ... print(rnd(2.8 - 1.3), 2.8 - 1.3) print(rnd(1.8 - 1.3), 1.8 - 1.3) print(rnd(-2.8 + 1.3), -2.8 + 1.3) print(rnd(-1.8 + 1.3), -1.8 + 1.3) results ... 2.0 1.4998 1.0 0.5 -2.0 -1.4998 -1.0 -0.5 we have to define limits caused by the floating point internal representation but for general use in my opinion can work fine. do you see other cases where it cracks? -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: print(a := rnd(rnd(2.8-1.3, 15))) print(b := rnd(rnd(1.8-1.3, 15))) print(a == b) results ... 2.0 1.0 False it's the last significative digit that have problems, we could work on the code to correct this and experiment if someone is interested. by the way the last ultra successful excel 365 - i've just tried - have the same problem. we can do better then ms? -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: i want to be more clear, these could be useful. https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/round-function This VBA function returns something commonly referred to as bankers rounding. So be careful before using this function. For more predictable results, use Worksheet Round functions in Excel VBA. https://docs.microsoft.com/en-us/dotnet/api/system.math.round?view=netcore-3.1 Rounding to nearest, or banker's rounding Midpoint values are rounded to the nearest even number. For example, both 3.75 and 3.85 round to 3.8, and both -3.75 and -3.85 round to -3.8. This form of rounding is represented by the MidpointRounding.ToEven enumeration member. Rounding to nearest is the standard form of rounding used in financial and statistical operations. It conforms to IEEE Standard 754, section 4. When used in multiple rounding operations, it reduces the rounding error that is caused by consistently rounding midpoint values in a single direction. In some cases, this rounding error can be significant. this is how work the current round() function, but if i don't need to do successive rounding but only adjust data i prefer... https://docs.microsoft.com/en-us/dotnet/api/system.math.round?view=netcore-3.1 Rounding away from zero Midpoint values are rounded to the next number away from zero. For example, 3.75 rounds to 3.8, 3.85 rounds to 3.9, -3.75 rounds to -3.8, and -3.85 rounds to -3.9. This form of rounding is represented by the MidpointRounding.AwayFromZero enumeration member. Rounding away from zero is the most widely known form of rounding. i can understand in decimal the default is banking or accounting rounding and i can adjust the context, but in normal calculations i think will be more usefule the common rounding, or also the possibility to choose with an argument. i have simply implemented my functions, this is only for the sake of improving the language. cheers. -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: revision of "if you need to realize decimal.ROUND_DOWN function trunc is already fine." --> "if you need to realize decimal.ROUND_DOWN function int() or math.trunc() are already fine." -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
marco_ocram added the comment: about floats ... https://docs.python.org/3/library/functions.html#round "if two multiples are equally close, rounding is done toward the even choice (so, for example, both round(0.5) and round(-0.5) are 0, and round(1.5) is 2)" i'm sure lots of users don't need this but a common math rounding as ... https://docs.python.org/3/library/decimal.html#rounding-modes decimal.ROUND_HALF_UP and as option in some cases decimal.ROUND_UP the proposed function realize just this, for either positive and negative vals. if you need to realize decimal.ROUND_DOWN function trunc is already fine. i'm as mathematician have never used other roundings, i know the current round function work well in the accounting fiels but only there. in other languages sometimes the same problem (for example ms ones as old vb), really i and others don't know the reason. about the revision of the standard function to accept an additional argument for different rounding types, for example all available for decimals, is ok for me, better if the default will be the normal accepted math rounding decimal.ROUND_HALF_UP ... https://docs.python.org/3/library/decimal.html#decimal.BasicContext decimal.BasicContext This is a standard context defined by the General Decimal Arithmetic Specification. Precision is set to nine. Rounding is set to ROUND_HALF_UP. about the floating point approximation in my opinion if you aren't a scientist you can find it pretty nice if you apply the right roundings. i think to have documented enough my request. take care. -- ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com
[issue41598] rnd() + rndup() in math
New submission from marco_ocram : hello, please insert following simple but useful roundings in new lib math. def rnd(x, n=0): a = x*10**n b = int(a) if abs(a - b) >= 0.5: b += 1 if x >= 0 else -1 return b/10**n def rndup(x, n=0): a = x*10**n b = int(a) if abs(a - b) > 0: b += 1 if x >= 0 else -1 return b/10**n thanks a lot, marco. -- components: Library (Lib) messages: 375695 nosy: marco_ocram priority: normal severity: normal status: open title: rnd() + rndup() in math type: enhancement versions: Python 3.9 ___ Python tracker <https://bugs.python.org/issue41598> ___ ___ Python-bugs-list mailing list Unsubscribe: https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com