This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Adding support for rounding modes to builtin round
Type: enhancement Stage: resolved
Components: Library (Lib) Versions: Python 3.10
process
Status: closed Resolution: rejected
Dependencies: Superseder:
Assigned To: Nosy List: eric.smith, marco_ocram, mark.dickinson, rhettinger, ronaldoussoren, steven.daprano, stutzbach, tim.peters, veky
Priority: normal Keywords:

Created on 2020-08-20 09:39 by marco_ocram, last changed 2022-04-11 14:59 by admin. This issue is now closed.

Messages (29)
msg375695 - (view) Author: (marco_ocram) Date: 2020-08-20 09:39
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.
msg375698 - (view) Author: Ronald Oussoren (ronaldoussoren) * (Python committer) Date: 2020-08-20 11:09
Adding new functions that are extreme similar to existing functions requires a better rationale than your giving.

In particular, both are similar to the builtin function "round" (https://docs.python.org/3/library/functions.html#round>).
msg375709 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-20 13:12
If we want to proceed with this, much better way would be to add a rounding mode optional argument to `round` builtin.

But really, anyone trying to precisely round a decimal representation of a binary floating point number is, to paraphrase von Neumann, living in the state of sin. See https://stackoverflow.com/a/51146310/1875565.
msg375723 - (view) Author: (marco_ocram) Date: 2020-08-20 17:50
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.
msg375724 - (view) Author: (marco_ocram) Date: 2020-08-20 17:53
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."
msg375727 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-20 18:38
ROUND_HALF_UP is not chosen because it's popular, but because it's the best way to compensate for errors in representing decimal numbers by binary numbers.

Thinking that floats are decimal numbers is going to bite you anyway sooner or later. For example, would you expect (with your implementation) rnd(2.8-1.3) == rnd(1.8-1.3) ?
msg375729 - (view) Author: (marco_ocram) Date: 2020-08-20 18:50
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.
msg375730 - (view) Author: (marco_ocram) Date: 2020-08-20 19:21
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?
msg375731 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-20 19:30
Yes, we can do better than ms (whatever that means). And we do exactly that in the `decimal` module. Floats are not the right target for your algorithms, because they don't have decimal digits. It's as if you're trying to round words in English language. :-D (In fact, with words you'd probably have better luck, since they _can_ represent decimal numbers exactly.)
msg375746 - (view) Author: (marco_ocram) Date: 2020-08-21 08:02
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.4999999999999998
1.0 0.5
-2.0 -1.4999999999999998
-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?
msg375748 - (view) Author: (marco_ocram) Date: 2020-08-21 09:11
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.
msg375749 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-21 09:38
Yes, and these functions are completely fine for your personal library, if you need such things. But they really have no place in math module, since (1) they aren't always correct, (2) it's incredibly difficult to characterize exactly when they are, and (3) even when they are correct, they just give people wrong impression about floats somehow being decimal numbers.

If you need to use floats, reconcile yourself with the idea that they don't represent all decimal numbers, not even the ones with just one decimal place, and any algorithm dealing with decimal digits will be just an approximation.

If you want the best approximation the humanity can muster, backed with empirical data and theoretical considerations, use the round() builtin. 

If you want to just have something that works according to your preconceived notions in some cases, while failing mysteriously in others, use your quick-and-dirty implementations.

If you want exact decimal results, use the decimal module, and specify the rounding mode as you wish.
msg375779 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-08-22 04:45
Vedran: you are quoting von Neumann out of context, he was talking about generating random numbers, not rounding, and in the seven decades since he made his famous witticism, we of course know that there is absolutely nothing wrong with generating random numbers via arithmetical methods so long as you do it correctly :-)

I have read your comments in the linked Stackoverflow answer, and I don't agree that we shouldn't be rounding binary floats. I do, however, agree with your comment here that we ought to add a rounding mode to the built-in round function, that would be a much better idea than adding a multitude of individual rounding functions.

I proposed this idea some time ago:

https://mail.python.org/archives/list/python-dev@python.org/message/DVS3XSAKW37NDD37BE3IOCKRBRV3Y5A6/
msg375781 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-08-22 05:17
Marco, it is better to give a description of the functionality required rather than a simplistic and incorrect implementation :-)

(Not that I am likely to provide a better implementation without a lot of study.)

Regardless of whether you or I agree with the decision to move to Banker's Rounding, that was done about a decade ago, and it matches decisions made by other languages such as Julia. Changing the default will break people's code and we do not do that lightly, or at all, without a very good reason.

As Tim Peters describes here:

https://mail.python.org/pipermail/python-dev/2008-January/075873.html

many older languages implemented rounding by "add half and chop", more because it was cheap than for its mathematical properties.

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.

Vedran: I don't think the availability of different rounding modes will have any effect at all on whether or not people believe floats are real decimal numbers rather than binary floats. People already believe that. I think we are better off acknowledging that there are reasonable use-cases for different rounding modes even when using floats.

According to this:

https://www.gnu.org/software/libc/manual/html_node/Rounding.html

IEEE-754 only requires four rounding modes, defaulting to the same Banker's Rounding that Python uses. Wikipedia says there are five:

https://en.wikipedia.org/wiki/IEEE_754#Rounding_rules


Regardless of whether there are four or five, I see no technical reason why we couldn't offer the full set of eight used by the decimal module.
msg375786 - (view) Author: (marco_ocram) Date: 2020-08-22 08:09
@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.
msg375787 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-22 08:30
I think you don't know what paraphrasing means. Or maybe I don't know it, but in any case, I'm well aware what Von Neumann said, and how it is usually misunderstood in today's society. "Living in the state of sin" is simply an emotionally powerful metaphor, and it pertains to the philosophical impossibility of something, whether or not there are strong reasons to "do it anyway" and even good methods of faking/approximating it. Same as "detecting infinite loops programmatically", "passing objects by value", or "having side effects in a referentially transparent language". :-)

I agree that Python is a language where practicality beats purity, and as I said, there is a sensible interface for the implementation about which we agree (except for a detail: I'd actually _force_ people to import the rounding modes from decimal module, to at least hint to them what exactly they are doing and what the preferred approach is). But I still think that arguments for that are very weak.

First, yes, there is a very small probability of calculations _randomly_ ending with abc.de50000...0 (in the Platonic sense) [so it actually manifests as a problem], but there is much greater probability (though still small) that calculations _theoretically_ ending with abc.de5 actually end with abc.de49999...7 [and thus are rounded down anyway, despite your insistence on modes]. People _will_ think "hey, I did the right thing by specifying the mode--why does it still acts funny?"

"there are reasonable use-cases for different rounding modes even when using floats.": absolutely. But they are _binary_ rounding modes! I think you should read the standard. It is actually two standards, one for binary and one for decimal arithmetic. (The second one is implemented fairly faithfully in the decimal module; the first one is, through libc, the one that Python floats are based upon).

The [binary] standard says, more or less, that the result should be as if the value was calculated with the infinite number or extra [binary] digits (of course, in practice it should just be some extra precision, but again, of _binary_ digits), and then, when fitting that value into a smaller [binary] register with smaller available number of [binary] digis, all extra [binary] digits are discarded (not stored) and some ending [binary] digits retained are modified according to the value of some of the discarded [binary] digits and the rounding mode. For example:

"""
The 24-bit significand will stop at position 23, shown as the underlined bit 0 above. The next bit, at position 24, is called the round bit or rounding bit. It is used to round the 33-bit approximation to the nearest 24-bit number (there are specific rules for halfway values, which is not the case here). This bit, which is 1 in this example, is added to the integer formed by the leftmost 24 bits.
"""

You see it speaks about _bits_, not decimal digits. In the same way, _decimal_ rounding would take a value calculated with some extra precision of _decimal_ digits, and when storing them with the smaller number of _decimal_ digits, discard extra... blah blah as above. But you cannot round binary numbers to decimal digits. It's as if you tried to round 0.45 to one trinary digit after the integer point. The answer is 0.1 in base 3, but it isn't expressible in decimals. And it doesn't work:

>>> Decimal('0.45').quantize(Decimal(1/3))
decimal.InvalidOperation: [<class 'decimal.InvalidOperation'>]

because the authors of quantize have thought about that. The documentation says """Unlike other operations, if the length of the coefficient after the quantize operation would be greater than precision, then an InvalidOperation is signaled.""" In effect, rounding cannot increase the number of significant digits. And it would do that if you're rounding to an incompatible base, whether 2 to 10 or 10 to 3.
msg375803 - (view) Author: (marco_ocram) Date: 2020-08-22 17:23
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.
msg375804 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-22 18:28
> use more digits to manage rounding in decimal base, not only one but more (i should think better and experiment on how many)

You don't have to. It's infinitely many. :-P Think, how many decimal digits would you need to accurately round numbers to a closest third (one trinary digit)? Here are some decimal digits: 2.166666666. If the next digit is 5, then it rounds to 2.0. If it is 7, it rounds to 2.1 (base 3). If it is 6, you still don't know anything. It can go arbitrarily far. Of course, the probability is lower with every digit, and at some point it becomes acceptable (you said for yourself it's acceptable even with one extra digit), but it's not mathematically correct.

And that one bit was just an illustration. In real life, 64-bit machines usually use at least 80-bit precision, so 16 extra bits. But it doesn't help your case, for the above reasons: this is simply not decimal rounding.
msg375869 - (view) Author: Steven D'Aprano (steven.daprano) * (Python committer) Date: 2020-08-25 02:46
Okay Marco, I'm changing the title to reflect the new API (support for rounding modes rather than new round functions) and pushed the version to 3.10, since 3.9 is in feature freeze (no new features).

This will probably need to be discussed on Python-Ideas, and maybe a PEP written, but provided it is not too controversial it may not be a big complicated PEP and I'm happy to help.

There is certainly a history of people requesting something like this:

https://kingant.net/2019/01/rounding-numbers-in-python-2-and-python-3/

https://mail.python.org/archives/list/python-dev@python.org/thread/34QNDXZBMP6RR4P6NZFFIJK6YODEWSVK/


It will help very much if Mark, Raymond and Tim either support this idea or at least don't object. (Adding Tim to the nosy list.)

See also relevant discussion here:

https://bugs.python.org/issue32956


In my innocence, I don't think that this will be a very difficult feature to implement. Out of the five IEEE-754 rounding modes:

- Round to nearest, ties away to even already exists, so no extra work needs to be done.

- Round to nearest, ties away from zero was already implemented in Python 2, so we can just(?) resurrect that.

- Round toward 0 (truncation or chop) is equivalent to rounding down for positive numbers and rounding up for negatives, so if we can implement those, we get round towards 0.

- And I think that rounding up and rounding down are symmetrical, so if you can do one, you can do the other.

As Vedran correctly points out, the tricky part is adjusting for the difference between decimal digits and bits.

Dotnet provides rounding modes for Math.Round:

https://docs.microsoft.com/en-us/dotnet/api/system.midpointrounding?view=netcore-3.1


So does Julia:

http://www.jlhub.com/julia/manual/en/function/round

http://www.jlhub.com/julia/manual/en/function/get_rounding


so I think that there is precedence for this in other languages.
msg375885 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2020-08-25 10:30
> I don't think that this will be a very difficult feature to implement.

Agreed that it shouldn't be hard to implement, if we do the obvious thing (rounding the exact value that the float represents, rather than trying to do some sort of Do What I Mean rounding). But I'm far from convinced that it's a good idea. I think it'll increase user confusion and generate lots of spurious "Python's round is broken" bug reports.

To be clear: supporting rounding modes for rounding from float to integer is fine (i.e., supporting the ndigits=0 case, or the case where ndigits is not supplied at all). The confusion is going to arise with rounding to a particular number of decimal places with a given rounding mode.

Note: there are two parts to this - the first part is figuring out what functionality we want. The second part is figuring out how best to spell it (separate functions versus keyword arguments to round, etc.). I'm mostly ignoring the second part for now and concentrating on the first part. There's a lot to discuss with the second part too (e.g., how does the __round__ protocol change, in a way that doesn't break 3rd party types already using it; how do we specify rounding modes, etc.), but it doesn't seem so useful to have that discussion until the first part is figured out.

Two examples to illustrate, one with a round-to-nearest rounding mode, one with a directed rounding mode:

- 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.

- 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.

Tricks like the power of 10 scaling in the original post aren't really a solution: they just serve to make it even less predictable when the users' expected result will appear and when it won't, and likely give a false sense of security.

If we were to implement this, there's a choice to be made: do we (1) base the rounding on the actual float value and do correct rounding, as round currently does, or do we (2) try to do something magic that guesses what value the user actually meant, rather than rounding the exact value that the round function receives? I _really_ _really_ don't want to go down the DWIM path of option (2), but I suspect that (1) will be mostly useless for users, outside the ndigits=0 use-case. There _are_ valid use-cases for two-argument round on floats (e.g., casual binning), but for the most part round already fills those use-cases.

I'd rather add whatever bells and whistles we need (if any) to make it easier for users who care about this to use Decimal.
msg375887 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-25 11:28
> I'd rather add whatever bells and whistles we need (if any) to make it easier for users who care about this to use Decimal.

This made me think. (I have tons of these ideas, but usually am afraid of voicing them unless encouraged by comments such as this one.;) How about this whistle: we allow round to accept str as the first argument?

In a very unrelated context (https://www.python.org/dev/peps/pep-0484/#forward-references) Guido has said something like "when literals aren't what they seem, strings are a good enough substitute". Maybe here too?
msg375903 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2020-08-26 05:02
Like Mark, I'm not convinced this is a good idea.  

Outside of finance calculations which typically already use decimal, the need for it is somewhat rare.  Also, the API doesn't fit neatly with existing the __round__ dunder methods, so the new feature couldn't be made to work with existing classes.

If you want to pursue this, I recommend taking it to python-ideas.
msg375921 - (view) Author: (marco_ocram) Date: 2020-08-26 08:43
"- 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.49999...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.50000...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.
msg375933 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-08-26 14:37
I don't think we should add this. It will often surprise the user. We get enough .1+.2 != .3 reports as it is, and this would be just as problematic.
msg375935 - (view) Author: Mark Dickinson (mark.dickinson) * (Python committer) Date: 2020-08-26 15:44
@Vedran:

> I have tons of these ideas, but usually am afraid of voicing them ...

Always good to have ideas brought up, so long as there's no expectation that every idea gets implemented. :-) But I think rounding a string is probably another one for the python-ideas mailing list. (Personally, I think I'd rather have easier ways to create Decimal objects than have strings become a kind of proxy for Decimal objects - e.g., `round(2.675d, 2)` rather than `round("2.657", 2)`.)
msg375940 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-26 17:06
> Personally, I think I'd rather have easier ways to create Decimal objects

Wouldn't everybody? :-P But that's been proposed at least 4 times already and never got anywhere. My proposal is at least original, has a precedent at the above link (strings as surogate literals, preserving value across semantic boundaries), _and_ comes with a natural scope limitation guarantee: noone can argue for '2.1' + '3.5' to be '5.6' (because it is already '2.13.5';), it works only in the first argument of round.

Also, the string at that time is not so pointless: many people use round for printing, at that point you are going to convert to str anyway. And round(str(result), digits) gives a nice way to use python's builtin repr capability of "picking the shortest representation" for DWIMming: it's the best of both worlds, your implementation DWIMs, but you're not responsible for corner cases. ;-=

But no, I'm not going to Python-ideas, for the same reason I'm not going back to high school: too many bullies, too hard to get your voice heard, mostly because everyone assumes you wouldn't be there if you had anything smart to say. :-/
msg375944 - (view) Author: Eric V. Smith (eric.smith) * (Python committer) Date: 2020-08-26 18:01
If you're using round(str(some_float), digits) and the result is a float, then that's a problem, since you're going to round it again for display at some point.

If you want a string result, you're better off using format(float, format_spec), or f-strings, or str.format() (all of which have the same underlying implementation) to do your float-to-string-for-display-purposes work.

I just don't see how getting a binary float via decimal rounding would be useful.
msg375953 - (view) Author: Vedran Čačić (veky) * Date: 2020-08-26 18:46
Well, of course, but that's possible even now, and people still reach for `round`. I guess the problem is that it's too easily accessible. :-)
msg375959 - (view) Author: Raymond Hettinger (rhettinger) * (Python committer) Date: 2020-08-26 20:53
Given that most of commenters don't think this is a good idea, I'm going to mark it as closed.  Feel free to continue the discussion on python-ideas.  If it gains traction, open this back up and give it more core-developer attention.
History
Date User Action Args
2022-04-11 14:59:34adminsetgithub: 85764
2020-08-26 20:53:00rhettingersetstatus: open -> closed
resolution: rejected
messages: + msg375959

stage: resolved
2020-08-26 18:46:51vekysetmessages: + msg375953
2020-08-26 18:01:06eric.smithsetmessages: + msg375944
2020-08-26 17:06:36vekysetmessages: + msg375940
2020-08-26 15:44:50mark.dickinsonsetmessages: + msg375935
2020-08-26 14:37:41eric.smithsetnosy: + eric.smith
messages: + msg375933
2020-08-26 08:43:21marco_ocramsetmessages: + msg375921
2020-08-26 05:02:27rhettingersetmessages: + msg375903
2020-08-25 11:28:33vekysetmessages: + msg375887
2020-08-25 10:30:06mark.dickinsonsetmessages: + msg375885
2020-08-25 02:46:11steven.dapranosetnosy: + tim.peters
title: rnd() + rndup() in math -> Adding support for rounding modes to builtin round
messages: + msg375869

versions: + Python 3.10, - Python 3.9
2020-08-22 18:28:24vekysetmessages: + msg375804
2020-08-22 17:23:35marco_ocramsetmessages: + msg375803
2020-08-22 08:30:41vekysetmessages: + msg375787
2020-08-22 08:09:03marco_ocramsetmessages: + msg375786
2020-08-22 05:17:02steven.dapranosetmessages: + msg375781
2020-08-22 04:45:44steven.dapranosetnosy: + steven.daprano
messages: + msg375779
2020-08-21 09:38:43vekysetmessages: + msg375749
2020-08-21 09:11:23marco_ocramsetmessages: + msg375748
2020-08-21 08:02:28marco_ocramsetmessages: + msg375746
2020-08-20 19:30:37vekysetmessages: + msg375731
2020-08-20 19:21:00marco_ocramsetmessages: + msg375730
2020-08-20 18:50:54marco_ocramsetmessages: + msg375729
2020-08-20 18:38:15vekysetmessages: + msg375727
2020-08-20 17:53:04marco_ocramsetmessages: + msg375724
2020-08-20 17:50:28marco_ocramsetmessages: + msg375723
2020-08-20 13:12:16vekysetnosy: + veky
messages: + msg375709
2020-08-20 12:47:40xtreaksetnosy: + rhettinger, mark.dickinson, stutzbach
2020-08-20 11:09:35ronaldoussorensetnosy: + ronaldoussoren
messages: + msg375698
2020-08-20 09:39:37marco_ocramcreate