If you compare a number with a string or the comparison
involves numerical strings, then each string is converted
to a number and the comparison performed numerically. If you compare a number with a string or the comparison
involves numerical strings, then each string is converted
to a number and the comparison performed numerically.I'm currently working with barcodes: numerical strings from 6 to 55 digits. In no way can I risk having one barcode be evaluated as equal to a literally different barcode just because the symbols in that string just happen to exhibit a passing resemblance to data of a different type.
Again, it's not just that it has loose typing. It's that it's taking what is OBVIOUSLY a string, converting it to an integer, THEN converting it to yet another data type which imposes data loss.
Intolerable for real-world use. A toy language. Alas, PHP, we hardly knew you...
ETA: Oh, I'd love to know the justification for the downvoting.
Have you been out on the internet the past decade? Do you have a tendency to make extremities of things and trying to stand the needle on its tip?
Making extremes? My medical application would fail FDA approval in minutes if ported to PHP precisely because of this issue.
Btw, PHP's behavior doesn't totally make sense to me either. But I'm willing to assume that its users and designers have thought this through and it makes sense for PHP's intended use cases, because I don't know PHP.
Javascript (which most people on HN seem to like) also has similar issues (null vs. undefined, == and === etc). It got so bad that "Javascript: the good parts" had to be written to define a de-facto sane subset of the language. People are actually writing in Coffeescript (in part) to avoid Javascript's pitfalls.
YMMV.
There are actually some decent commercial PHP IDEs, believe it or not. I wouldn't be surprised if some of them are able to Warn on loose equality comparisons. I don't have much direct experience with them though.
By making the constant the expression's lvalue. But they don't have to do this anymore; gcc warns when you accidentally use = instead of == now.
I'm sorry, I would like that to be true, but programmers rarely are half as smart as they think they are. We have many more years of PHP and its resulting insanity ahead of us.
Your lack of knowledge does not make it obscure.
So you could have predicted this yesterday? Just because it's codified somewhere, it doesn't make it clear, or anything other than a whim, or a product of circumstances, at best. That's not how languages should be defined, even if PHP clearly demonstrates that they can end up that way by chance.
Rasmus' lack of foresight does not make it reasonable.
In fact, this behavior has been documented explicitly for a year and a half: http://web.archive.org/web/20100808122711/http://www.php.net...
Earlier versions have said the comparison converts the numbers to integers though, which may be incorrect, and misleading if it was. Did PHP not convert float-like strings to floats in, eg, 2009? http://web.archive.org/web/20091024233139/http://www.php.net...
The point, however, is that you shouldn't pepper your language with operations which have consequences as hard to foresee as this with no good reason, and I really don't think that saving yourself some type conversions here and there would do.
The same kind of logic is used to make `false == ""` true. Or any 'falsy' language. If you want strictly typed behavior, yes, it's stupid to do that. If you don't, then it makes some things simpler, at the expense of more edge cases that are unlikely to happen - note that this bug was reported in 2011, and people are acting like it's a new thing. Because it comes up so rarely that, while it technically exists, many people never encounter it.
You are right, in a way. Sure, it may attract and retain more newcomers, but that's like saying that tobacco is "teenager friendly". I think it's not beginner friendly at all if you must have years of experience to avoid the innumerable pitfalls which PHP lays for you all over the place, learning, e.g. the range of Integers in PHP, which defines when a string will be either a float or an int, or that you should actually use strcmp.
In Python, Ruby, or heck, Haskell, you'd just have to do == and there would be no surprises.
This essentially breaks down to the top-down vs bottom-up education style debate. You can learn the gritty details and get caught up in minor details that may not matter in other languages, or learn how to do something, and get tripped up by the details in other languages. Similarly, we could teach kids abstract algebra, or basic +-*/ and then over-simplify when they try to divide by zero.
Neither is ideal, both have useful traits and problems, so we have to pick one. Or try to come up with something radically different.
edit: to ask it another way: if PHP is a massively-popular gateway drug to the world of programming, but it gives some people horrible flashbacks for the rest of their lives, do you want to make it illegal and close the door to a huge number of people?
Oh, and "everyone knows that PHP lights the upper-rightmost pixel in you screen purple and will crash if there's no screen" would not, in fact, justify such a thing.
You must hate programming then.
9223372036854775807.0 == 9223372036854775808This tripped me up when I was trying to compare two numbers, one of which was the result of a COUNT query via PDO. Of course, that COUNT result was a string.
I suppose if you worked entirely with strings it's alright. Or it wouldn't be so bad if you could make the reasonable assumption that functions returned appropriately typed data.
Seems like a silly thing to say. I wouldn't write avionics software with it, but there are a billion websites demonstrating that it's pretty decent for real-world use. At least as good as any other language, I'd guess.
I was about to give an outraged reply that, if PHP is like Perl, then it doesn't scan the string afresh, just keeps a flag indicating whether or not it thinks a string is numeric. However, it turns out that's not true at all. `Perl_looks_like_number`, defined in `sv.c`, calls `Perl_grok_number`, defined beginning on l. 577 (as of v5.14.2) in `numeric.c`, which (after some book-keeping) does this:
if (s == send) {
return 0;
} else if (*s == '-') {
s++;
numtype = IS_NUMBER_NEG;
}
else if (*s == '+')
s++;
if (s == send)
return 0;
if (isDIGIT(*s)) {
UV value = *s - '0';
if (++s < send) {
int digit = *s - '0';
if (digit >= 0 && digit <= 9) {
value = value * 10 + digit;
if (++s < send) {
digit = *s - '0';
if (digit >= 0 && digit <= 9) {
value = value * 10 + digit;
if (++s < send) {
digit = *s - '0';
if (digit >= 0 && digit <= 9) {
value = value * 10 + digit;
and goes on and on and on and on in the same vein. Sheesh! (I didn't forget to close that last brace; the next line is de-dented, but that seems to be a mistake.)Edit: I know == is not a string comparison. But you'd expect it to fail in a predictable way when passed strings that are not parseable as numbers, instead of trying to fall back on a string comparison so that people get the wrong idea.
This hamdriver you speak of: tell me more.
I generally avoid exceptions/error_levels in all languages but this is probably a good cause for them, in order to keep the rest backwards compatible.
In this case in php, the truncation happens due to loss of precision in the mantissa of the double precision float. But there are so many other ways to lose precision, I don't think it's reasonable to ask a language to attempt to account for them.
This is why languages should have clear rules about when type conversion occurs, and allow the user to prevent it when it isn't desirable.
edit: in fact, amusingly, php seems to be doing some non-standard stuff with its floats. I was going to make a point about how you can't determine if a double is a "correct" representation of a string decimal, but in mocking an example I discovered something odd. Check this out:
This is what one should expect:
$ ruby -e'puts "%5.25f" % 0.1'
0.1000000000000000055511151
$ perl -wle'printf "%5.25f\n", 0.1'
0.1000000000000000055511151
But in php:
$ php -r'printf("%5.25f\n", 0.1);'
0.1000000000000000000000000
$ php -r'printf("%5.25f\n", "0.1");'
0.1000000000000000000000000
Is php changing the type conversion? Or not using double precision at all?
[1] This doesn't really happen in PHP, but you have $php_errormsg that can be set without stopping execution (as happens with some errors/warnings when error_level is not set to E_STRICT, and below that depending on the error). This errors could be triggered in a new level, let's say "E_PEDANTIC".
We have two distinct problems here:
- strings converting to numbers without there being any number on any side. "Peculiar" of PHP but easy to circumvent using string comparison. IMO belongs in PHP4 but not at all in PHP5, which is an attempt at a "general-purpose" language. To be frank, I thought PHP4 made more sense because it was 1st of class at what it did, while PHP5 falls short to a number of languages in basically everything.
- automatic integer-to-float comparison to accomodate bigger integers. A horrible hack to squeeze a little extra performance in naive benchmarks in computers with no native 64 bit integer support. This really makes no sense whatsoever now and may have had some partial justification in the early 90s, prior to PHP4 even.
Both ideas are terrible and pretty much unique to PHP of all popular languages.
This is not a philosophical debate about typing styles or the existence of perfect type conversions. PHP's problems in this regard are relics from a dubious past.
No, this is not unique to php. Many popular, comparable languages perform an int -> float conversion. For example, Perl:
$ perl -wle'print "20938410923849012834092834" + 0 if "20938410923849012834092834" == "20938410923849012834092835"'
2.0938410923849e+25
- This is not a philosophical debate about typing styles or the existence of perfect type conversions. PHP's problems in this regard are relics from a dubious past.
Conversion from string -> number, and loose numeric types which auto-convert to float are near universal in loosely typed languages, out of necessity -- if such a scheme doesn't work consistently it can't be used at all. This brings me back to my point. You said "IMO this conversion should fail if the number represented is not valid, or fall back to arbitrary precision math". My response is that you cannot provide such a rule on the basis of "is it valid" because there is no such thing as a "valid" type conversion -- ALL have precision loss. It is inherent in the datatype. When I said "you may be underestimating the difficulty in predicting whether a particular decimal number can be accurately represented as a floating point type" you should perhaps read that as "you cannot do this, it is not possible".
Instead you might suggest that no loose conversion, no loose typing be permitted in a language design -- and I would agree wholeheartedly. But your suggestion that this be handled on a case-by-case basis depending on the numeric value is fundamentally unworkable. Big integers are not the only area this type of problem presents.
This, now, where it's being used, is absurd. There is no two ways to that. And this doesn't happen elsewhere to this extent.
I will leave you the last word though. Cheerio.
Your suggestion would make type conversion utterly unusable as it would fail seemingly randomly -- for example on simple numbers such as "0.1"
I am happy to see you agree with me.
This reminds me of Excel-like programs that by default, automatically detect (and convert) fields that appear to be dates/strings...often to catastrophic effect.