It seems very counterintuitive to me that mathematical operators would change numeric types, I'd expect that adding extra magic type-conversion rules to a language in which everything type-related is already done magically will increase your potential for bugs.
A false midnight
Posted Mar 20, 2014 13:31 UTC (Thu) by zuki (subscriber, #41808) [Link]
> It seems very counterintuitive to me that mathematical operators would change numeric types
I don't understand that... In "real" math, integers are also reals, and 5 is exactly the same as 5.0, and 4.999..., and nothing should change if one is substituted with the other. And operations *do* change type, e.g. with division, raising to the power or logarithm with might get a (non-integer) real from integers, and on the other hand, floor and ceiling and division or multiplication, we might get an integer from reals... I like it when Python keeps up this illusion, whenever feasible.
A false midnight
Posted Mar 20, 2014 15:43 UTC (Thu) by renox (subscriber, #23785) [Link]
A false midnight
Posted Mar 20, 2014 16:16 UTC (Thu) by apoelstra (subscriber, #75205) [Link]
Often there are implicit embedding maps from, as in your example, the integers into the reals. As long as they are actual embeddings (i.e. injective and a homomorphism of the appropriate type) they are left implicit, but otherwise you need explicit maps to move between types. And in fact this type information can cause confusion; exponentiation might map from a group of numbers under addition to a group under multiplication --- and if these groups have the same (or nearly the same) underlying set, it can cause confusion and bad logical implications, for exactly the same reason that type conversions are a source of bugs in programming.
So it is nothing new that 2 and 2.0 are different types in programming. (Though the truncating behaviour of '/' is pretty weird --- in mathematics the integers are not a division ring and division is not done on them in general.) And in programming there are dramatic differences: for one thing, there is no 'real' type since almost all reals cannot be described in finite information, while every integer can. With floating point types, all arithmetic operations are approximations (and their errors can compound in surprising ways) while integer operations are precise (everywhere that they are defined).
A false midnight
Posted Mar 20, 2014 20:28 UTC (Thu) by nybble41 (subscriber, #55106) [Link]
That's certainly an interesting way to look at it. Usually one doesn't consider the set an object was *selected from* to be an identifying characteristic of the object. The same object can belong to multiple sets, and, mathematically speaking, there is no difference between 2, 2/1, and 2.0. The number 2 is a member of the set of integers, and the set of rationals, and the set of reals, all at the same time. It has a square root in the set of reals, but not in the set of integers. It's a unit in the rings of rationals and reals but not in the ring of integers. The set qualifier goes with the property (has an integer square root, is a unit in the ring of rationals), not the number.
I'm not quite sure what you mean when you say that "rational 2" is not prime... "rational 2" is the same number as "integer 2", which is a prime number. If you're referring to a different kind of prime, like a prime field, then you'll have to be more specific before you can classify 2 as prime or not.
A false midnight
Posted Mar 21, 2014 15:10 UTC (Fri) by apoelstra (subscriber, #75205) [Link]
The reason I look at it this way is because I have encountered "type errors" when building mathematical proofs, for example when working with two groups whose group operations are both denoted as multiplication. The extra mental effort to tag every object with its originating set, in order to see which operations are available and meaningful, feels exactly like the extra mental effort to analyze code in an implicitly typed language.
Often hypotheses in mathematical proofs are actually type declarations, as in "Let M be a compact closed manifold". Early "proofs" before the late 19th century would lack this type information (in fact people were unaware that they needed it) and the result was an enormous body of confused and incorrect mathematical work. For example it was common practice for "proofs" to have corresponding lists of counterexamples. This is evidence that it's very easy and natural for people to lapse into defective reasoning when faced with implicit typing. Though of course programmers have a big advantage over 18th-century mathematicians in that we know not only that the types are there, but also a complete (and small) list of all available types.
Maybe this is a confused analogy. But I don't think it is, and it's helpful to me in both mathematics and programming.
> I'm not quite sure what you mean when you say that "rational 2" is not prime... "rational 2" is the same number as "integer 2", which is a prime number. If you're referring to a different kind of prime, like a prime field, then you'll have to be more specific before you can classify 2 as prime or not.
It's a bit of an aside, but I mean prime in the sense of commutative rings: an element p is prime if it is (a) nonzero and not a unit, and (b) if p divides ab, it divides one of a or b.
In the ring of integers 2 is prime; in the ring of rationals 2 is not (because it is a unit, which means it has a multiplicative inverse).
A false midnight
Posted Mar 22, 2014 0:03 UTC (Sat) by mathstuf (subscriber, #69389) [Link]
Well, in algebra "1 - 1 + 1 - 1 + …" is undefined since algebra cannot reach the end; in the realm of infinite series, ½ is a valid value for the series (and the only one). There's a similar thing with any of ζ(n) when n is a negative odd integers (ζ(-1) = 1 + 2 + 3 + 4 + … = -1/12, ζ(-3) = 1 + 8 + 27 + 64 + … = 1/120, etc.). Computations definitely rely on the context in which they reside; I see no reason why numeric values would be exempt.
A false midnight
Posted Mar 22, 2014 9:54 UTC (Sat) by Jandar (subscriber, #85683) [Link]
A false midnight
Posted Mar 22, 2014 10:46 UTC (Sat) by mathstuf (subscriber, #69389) [Link]
[1]https://en.wikipedia.org/wiki/Particular_values_of_Rieman...
A false midnight
Posted Mar 22, 2014 15:23 UTC (Sat) by Jandar (subscriber, #85683) [Link]
A false midnight
Posted Mar 21, 2014 10:42 UTC (Fri) by moltonel (subscriber, #45207) [Link]
Do you also find it intuitive that adding 1 to a big enough value yields a very low negative value ? Some languages, python included, will convert that machine-level integer into an object that can store arbitrarily long numbers (BTW, it's transparent in python3, but python2 appends an 'L' suffix to that number), and that is a good thing in most cases.
Type-changing operators are actually common and expected, as long as they follow some common sense (how about the classic "date - date = duration" for example ?). And common sense says that numbers are numbers are numbers.
You only find "2/3=0" intuitive because you've been formated by years of using languages where this is the case for technical reasons. But tell that to any non-programmer or user of other languages and they'll be asking "WTF?". Python3 fixed that gotcha. This is a Good Thing.
A false midnight
Posted Mar 21, 2014 15:37 UTC (Fri) by apoelstra (subscriber, #75205) [Link]
I really don't like that in C, signed integer overflow is undefined behaviour -- in this case, I can't be sure of anything after the addition. :(
I like your "date - date = duration" example. I think you're right that POLS says division should have a floating-point output (and the truncation behaviour should be relegated to some other construct, e.g. a truncate() function), since what '/' does to ints in C is not, in fact, division.
In this case I can still be sure of the types of objects before and after the operation --- of course there is no intrinsic reason that these should be the same.
Copyright © 2018, Eklektix, Inc.
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds