On Sun, Sep 17, 2017 at 11:03 PM, Steve D'Aprano <steve+pyt...@pearwood.info> wrote: > On Sun, 17 Sep 2017 08:43 pm, Chris Angelico wrote: > >> On Sun, Sep 17, 2017 at 5:54 PM, Steve D'Aprano >> <steve+pyt...@pearwood.info> wrote: >>> To even *know* that there are branches of maths where int/int isn't defined, >>> you need to have learned aspects of mathematics that aren't even taught in >>> most undergrad maths degrees. (I have a degree in maths, and if we ever >>> covered areas where int/int was undefined, it was only briefly, and I've >>> long >>> since forgotten it.) >> >> How about this: >> >>>>> (1<<10000)/2 >> Traceback (most recent call last): >> File "<stdin>", line 1, in <module> >> OverflowError: integer division result too large for a float >> >> int/int is now undefined. > > No, it's perfectly defined: you get an overflow error if the arguments are too > big to convert, or an underflow error if the denominator is too small, or a > divide by zero error if you divide by zero... > > > What do you make of this? > > py> float(1<<10000)/2.0 > Traceback (most recent call last): > File "<stdin>", line 1, in <module> > OverflowError: int too large to convert to float > > > Would you like to argue that this shows that coercing ints to floats > is "undefined"? > > > Overflow and underflow errors are limitations of the float data type. We could > fix that in a couple of ways: > > - silently underflow to zero (as Python already does!) or infinity, as needed; > > - use a bigger ~~boat~~ float; > > - or even an arbitrary precision float; > > - or return a rational number (fraction or similar); > > - or introduce a float context that allows you to specify the behaviour > that you want, as the decimal module does. > > There may be other solutions I haven't thought of. But these will do. > > The distinction between Python floats and real numbers ℝ is a red-herring. It > isn't relevant.
You said: >>> (I have a degree in maths, and if we ever >>> covered areas where int/int was undefined, it was only briefly, and I've >>> long >>> since forgotten it.) So what do YOU mean by "int/int" being "undefined"? And I referred to real numbers because YOU referred to a degree in maths. >> In Py2, it perfectly correctly returns >> another integer (technically a long), but in Py3, it can't return a >> float, so it errors out. > > Apart from your "correctly", which I disagree with, that's a reasonable > description. The problem is that your example returns the correct result by > accident. Forget such ludicrously large values, and try something more common: > > 1/2 > > Most people aren't expecting integer division, but true division, and silently > returning the wrong result (0 instead of 0.5) is a silent source of bugs. > > This isn't some theoretical problem that might, maybe, perhaps, be an issue > for > some people sometimes. It was a regular source of actual bugs leading to code > silently returning garbage. So why doesn't it return a fractions.Fraction instead? That way, you still get "one half" instead of zero, but it's guaranteed to be accurate. And having 1/3 be a literal meaning "one third" would avoid all the problems of "1/3 + 1/3 + 1/3 != 3/3". What is the justification for int/int => float and not rational? >> In Python 2 and 3, a small integer can be implicitly promoted to float: >> >>>>> user_input = 3.14159 >>>>> print(user_input + 1) >> 4.14159 > > Yes, as it should. Why force the user to call float() on one argument when the > interpreter can do it? What advantage is there? > > Can you demonstrate any failure of dividing two ints n/m which wouldn't > equally > fail if you called float(n)/float(m)? I don't believe that there is any such > failure mode. Forcing the user to manually coerce to floats doesn't add any > protection. I don't think there is either, but by forcing people to coerce to float, you force them to accept the consequences of floats. Again, rationals (fractions.Fraction), implemented with a pair of arbitrary-precision integers, are a superset of integers, so you can genuinely upcast. Upcasting from one type to a non-superset of that type is problematic. Upcasting to a perfect superset isn't. ChrisA -- https://mail.python.org/mailman/listinfo/python-list