3 ms·
I don't see this as any different than coercion with other pairs of types.
by delinka 9y ago
I don't see this as any different than coercion with other pairs of types.
- sillysaurus3 9y agoI mean, sure, you can have that view. But again, what would you say should happen for 23n + 0.5? And for 9007199254740992n + 0.5? If you don't throw an error, you have to do something, and in those situations returning anything would be incorrect. You could return 23.5 in the former case, but then you'd no longer have an Integer. You could throw an error in the latter case, but that'd be a lot slower for JIT tracing compilers to execute than simply verifying that the types are the same.
- yladiz 9y agoTreat it as a arbitrarily large floating point value, rather than an integer.
- sillysaurus3 9y agoGood point, though in that case using arbitrary precision values anywhere in your program might tank performance. Execution speed still matters, especially now that we're at the physical limits of single cores, and automatically promoting to arbitrary floats seems like a poor trade of speed vs flexibility. It's way too tempting to "simply use arbitrary floats and be done with it", even in financial software, and then be in a situation where the entire program is slow. But it would be good to quantify how much slower it'd be. Animats pointed out a potentially more serious issue, which is that you can DoS a program by sending it an arbitrary precision number whose size is gigabytes. But that's true of any arbitrary precision number, not just floats.
- yladiz 9y agoI think in that case, internally it can handle smaller values differently than larger values (like Ruby). If the performance of large values is truly important, something using the FFI can be written to a program using something like C or Fortran.
- BerislavLopac 9y ago"You could return 23.5 in the former case, but then you'd no longer have an Integer." This works rather well in Python. >>> a = 10 >>> b = 1.1 >>> c = a + b >>> type(a) <class 'int'> >>> type(b) <class 'float'> >>> type(c) <class 'float'>
- sillysaurus3 9y agoThere's a solution to all of this: TAoCP has thought through these issues carefully, and it would probably be best to study the tradeoffs Knuth presented. Python handles common cases, but it breaks when you push it too far: >>> 1e100 1e+100 >>> 1e100+0.1 1e+100 >>> 1e100+0.1 == 1e100 True >>> 9007199254740992 + 0.5 9007199254740992.0 >>> 9007199254740992 + 0.5 == 9007199254740992 True >>> 9007199254740992 + 0.5 + 1 9007199254740992.0 >>> x = 9007199254740992 >>> y = x >>> y += 1 >>> x == y False >>> x = 9007199254740992 + 0.5 >>> y = x >>> x += 1 >>> x == y True You could argue that handling the common cases is all that's needed, but stuff like this pops up in e.g. writing software rasterizers. It might also be one reason why PyPy can't quite match the speed of native programs, though that's just a guess.
- orf 9y agoYou're right about those Python cases (and they are surprising!). But if you're dealing with numbers those big and adding decimals you would want to use the Decimal module: >> from decimal import Decimal as D >> 9007199254740991 + D('0.1') > Decimal('9007199254740991.1')
- SamReidHughes 9y agoIt wouldn't work well in JavaScript because it already has double-precision floats as its datatype used for both integers and floats. Python doesn't have floats getting used as integers, which is what leads to this problem.