Why does 1...1 evaluate to 10.1? [duplicate]
Asked Answered
P

4

168

I've just faced a little PHP snippet from 3v4l: https://3v4l.org/jmrZB

echo 1...1; //10.1

And I'm afraid I have no idea how to explain its results. Why is this considered valid at all?

Pump answered 17/7, 2017 at 8:55 Comment(3)
Note: the SO syntax highlighter makes the first dot red, while the others are black. This is a nice hint, I think. It would be nice if the last dot were red, too, but it's better than nothing.Devilfish
From nearly 3 months ago: reddit.com/r/lolphp/comments/684l1p/11_is_101Aestivation
tricky concatenation issue...Mares
A
221

The dot (.) has two roles in PHP:

  1. As decimal digit, when it is part of a real number, e.g. 1.1. Both the integral part and the decimal part are optional on real numbers but not on the same time. This means both 1. and .1 are valid real numbers in PHP but . is not a number.
  2. As the string concatenation operator. This operator connects two string sub-expressions into a larger expression. The value of the larger expression is the concatenation of the string values of the sub-expressions. The sub-expressions that are not strings are converted to strings before concatenation.
    E.g. 1 . 1 is the same as '1' . '1' and its value is the string '11'.

The expression 1...1 is parsed as 1. . .1. According to those said above, 1. and .1 are real numbers (1.0 and 0.1) and the middle dot (.) is the string concatenation operator.

When converts numbers to strings, PHP uses the minimum amount of characters required for this operation. If a real number has only integral part then it represents the number as integer, without decimal point and decimals.

This is why 1. . .1 is the same as '1' . '0.1' and the final value of the expression is 10.1.

Why is 1...1 parsed this way?

The parser reads the expression from left to right. 1 tells it a number starts there. 1. is a valid real number but 1.. is not. It keeps 1. as a number then the next dot is the concatenation operator. The next ., being followed by a digit, is the beginning of another real number (.1).

All in all, 1...1 is the same as 1. . .1.

Abloom answered 17/7, 2017 at 9:6 Comment(8)
I just tried echo 1/.1, it resulted in 10. How come it still concatenated the two integer even with just one .?Byers
@Swellar 1/.1 is divide 1 by 0.1 which is 10.Some
1/.1 is a number. It is 1 divided by 0.1. The value of expression 1/.1 is 10. There is no string involved.Abloom
@Abloom That makes sense, thank you. I just tried some things after reading this question.Byers
When we write it like this "1. . .1" (with spaces between middle dots) - then it makes things clear.Pump
The parser reads the expression from left to right. 1 tells it a number starts there, 1. is a valid real number, 1.. is not; it keeps 1. as a number then the next dot is the concatenation operator; the next ., being followed by a digit, is the beginning of another real number (.1).Abloom
Assuming that this answer is correct, why does neither 1..1 nor 1..1. print "11"?Skeet
The parser is greedy. It reads as much as it can while the fragment still makes a valid token. This is why 1. is a float number and not the integer 1 followed by the concatenation operator (.). For the same reason, 1..1 is 1. followed by .1 and 1..1. is 1. followed by .1 followed by ..Abloom
M
61

Because it's interpreted as 1. . .1 (1 and 0.1) therefore you get 10.1

Machismo answered 17/7, 2017 at 8:59 Comment(7)
Uhm, I thought ... was the splat operator, nice workBarvick
The . is a concatenation operation not a plus.Gaylagayle
Seems to make sense, but PHP does not concatenate numbers using dot in general, but here for some reason it does.Pump
php does what you tell it. Here you tell it concatenate items. As items are not string - php converts'em to strings.Some
There is no such thing as "concatenating numbers". Strings are concatenated; the numbers are first converted to strings before concatenation.Abloom
When we write it like this "1. . .1" (with spaces between middle dots) - then it makes things clear. That's why I was surprised, because we do not have spaces in the source.Pump
@DamienPirsy It is in other contexts, but it wouldn't make any sense to have a splat operator right after another value...Renault
U
45

Applying braces will make it clear:

(1.) . (.1)

  • 1. is interpreted as 1
  • . is string concatenation
  • .1 is interpreted as 0.1

This all put into a string is 10.1 as a string.

var_dump(1...1) yieldsstring(4) "10.1"

Unzip answered 17/7, 2017 at 9:7 Comment(2)
Applying braces is only clear if you already know where to apply them though.Newspaperman
@Newspaperman Thats why I have shown how to apply them.Unzip
I
22

Different Operations.

1. <?php echo 1.1; ?> // gives simple 1.1
2. <?php echo 1...1; ?> // gives 10.1
3. <?php echo 1..'1'; ?> // gives 11
4. <?php var_dump(1.); ?> // gives 1
5. <?php var_dump(.1); ?> // gives 0.1

Now, our strange operation

echo 1...1 

is treated as concatenation of no 4 and no 5, resulting in 10.1

Indignation answered 17/7, 2017 at 9:23 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.