Is there a speed difference between, say:
$newstring = "$a and $b went out to see $c";
and
$newstring = $a . " and " . $b . " went out to see " . $c;
and if so, why ?
Depending on the PHP version, it varies by how much the second is faster if you write it like:
$newstring = $a . ' and ' . $b . ' went out to see ' . $c;
PHP is very inconsistent from version to version and build to build when it comes to performance, you have to test it for yourself.
What nees to be said is that it also depends on the type of $a, $b and $c, as you can see below.
When you use ", PHP parses the string to see if there are any variable/placeholders used inside of it, but if you use only ' PHP treats it as a simple string without any further processing. So generally ' should be faster. At least in theory. In practice you must test.
Results(in seconds):
a, b, c are integers:
all inside " : 1.2370789051056
split up using " : 1.2362520694733
split up using ' : 1.2344131469727
a, b, c are strings:
all inside " : 0.67671513557434
split up using " : 0.7719099521637
split up using ' : 0.78600907325745 <--- this is always the slowest in the group. PHP, 'nough said
Using this code with Zend Server CE PHP 5.3:
<?php
echo 'a, b, c are integers:<br />';
$a = $b = $c = 123;
$t = xdebug_time_index();
for($i = 1000000; $i > 0; $i--)
$newstring = "$a and $b went out to see $c";
$t = xdebug_time_index() - $t;
echo 'all inside " : ', $t, '<br />';
$t = xdebug_time_index();
for($i = 1000000; $i > 0; $i--)
$newstring = $a . " and " . $b . " went out to see " . $c;
$t = xdebug_time_index() - $t;
echo 'split up using " : ', $t, '<br />';
$t = xdebug_time_index();
for($i = 1000000; $i > 0; $i--)
$newstring = $a . ' and ' . $b . ' went out to see ' . $c;
$t = xdebug_time_index() - $t;
echo 'split up using \' : ', $t, '<br /><br />a, b, c are strings:<br />';
$a = $b = $c = '123';
$t = xdebug_time_index();
for($i = 1000000; $i > 0; $i--)
$newstring = "$a and $b went out to see $c";
$t = xdebug_time_index() - $t;
echo 'all inside " : ', $t, '<br />';
$t = xdebug_time_index();
for($i = 1000000; $i > 0; $i--)
$newstring = $a . " and " . $b . " went out to see " . $c;
$t = xdebug_time_index() - $t;
echo 'split up using " : ', $t, '<br />';
$t = xdebug_time_index();
for($i = 1000000; $i > 0; $i--)
$newstring = $a . ' and ' . $b . ' went out to see ' . $c;
$t = xdebug_time_index() - $t;
echo 'split up using \' : ', $t, '<br />';
?>
There likely will be a speed difference, since it's two different syntaxes. What you need to ask is if the difference is important. In this case, no, I don't think you need to be worried. The difference would be too negligible.
I would recommend you doing whatever makes most sense to you visually. "$a and $b went out to see $c" can be a bit confusing when looking at it. If you wanted to go that route, I'd suggest curly-braces around your variables: "{$a} and {$b} went out to see {$c}".
I did a quick benchmark, and as others have said, the results were very inconsistent. I didn't notice any performance gain using single quotes instead of double ones. My guess is that it all comes down to preference.
You may want to stick to one type of quote for your coding style, and if you do, choose double quotes. The replacement feature comes in handy more often than you'd think.
I put the benchmark code on github.
If you're concerned about the speed of string concatenations at this level, you are using the wrong language. Compile an application in C for this use case and call that in your PHP script, if this really is a bottleneck.
Yes there is, however the difference is very negligible between
$newstring = "$a and $b went out to see $c";
and
$newstring = $a . " and " . $b . " went out to see " . $c;
If you used:
$newstring = $a . ' and ' . $b . ' went out to see ' . $c;
The difference would be slightly bigger (but probably still negligible), the reason for this is, if I recall correctly (I may be wrong on this), that PHP scans and parses the contents within double quotation marks for variables and special characters (\t, \n and so on) and when using single quotation marks it doesn't parse for variables or special characters, so there may be a slight increase in speed.
Why don't you test it, and compare the difference? Numbers don't lie, if you find that one performs better than the other, then you should ask why.
there is NO difference, period. ;)
Related
I have a class with field price. It's stored in database as varchar(100) (don't ask me why, not my idea) and I have to retrieve it and divide it by the other price, which is also retrieved from database.
In database number looks like: 1 000.00 - thousands' parts are separated with whitespace (one million looks like ->1 000 000.00).
I try it on website: w3resource.com/php with an online interpreter.
What I do is...
$a = "3 999.99";
$b = "1 500.11";
$aa = floatval(str_replace(' ', '', $a));
$bb = floatval(str_replace(' ', '', $b));
$c = $aa - $bb;
echo $aa . ' - ' . $bb . ' = ' . $c;
and it displays correct output:
3999.99 - 1500.11 = 2499.88
But when I do it in my project, it's like:
$a = "3 999.99";
$b = "1 500.11";
$aa = floatval(str_replace(' ', '', $a));
$bb = floatval(str_replace(' ', '', $b));
$c = $aa - $bb;
echo $aa . ' - ' . $bb . ' = ' . $c;
3999.99 - 1500.11 = 2.00
In my project, price is truncated - everything that is after the whitespace is truncated and the calculations are performed only on the first digits, in my case it's: 3 - 1
Could anybody tell me where to look for a bug?
Most likely you have a non visible character as the thousand separator character. It's more safe to filter all characters except digits and . when sanitizing the input string. This can be achieved with the preg_replace function.
Your script can be modified to something like this:
$a = "3 999.99";
$b = "1 500.11";
$aa = floatval(preg_replace('/[^0-9.]/', '', $a));
$bb = floatval(preg_replace('/[^0-9.]/', '', $b));
$c = $aa - $bb;
echo $aa . ' - ' . $bb . ' = ' . $c;
Additionally, it's a bit dangerous and non exact to use floats when handling money in particular. Please have a look at this repository which helps a lot with this problem: https://github.com/moneyphp/money
The biggest mistake is price as varchar(100) - it's a string, it can be displayed in a million ways, but it cannot be recalculated. There are no excuses. It should be an integer or decimal and any subtraction should be done using SQL.
The second error is when you use a float as the value for price. Leave php float for astrophysicists, use int.
$a = "3 999.99";
$b = "1 500.11";
$a1 = (int) preg_replace('/[^0-9]/', '', $a);
$b1 = (int) preg_replace('/[^0-9]/', '', $b);
var_dump($a1, $b1); // test
echo'<hr>';
$c1 = $a1 - $b1;
var_dump($a1, $b1, $c1); // test
formatting to display:
echo substr_replace(substr_replace($c1,' ',-5,0), '.',-2,0);
I need to print some numbers in a sequence with + and - between them. However, I don't know beforehand which number is going to be positive and which is going to be negative. Currently, I echo them like this:
echo "$a + $b + $c + $d + $e + $f";
Let's say the values of $a to $f are all positive. I will get something like: 5 + 10 + 12 + 18 + 9 + 7.
However, if some of the values are negative, I will get something like 5 + -10 + 12 + -18 + 9 + - 7. The ideal output in this case would have been 5 - 10 + 12 - 18 + 9 - 7.
Please not that I don't want to calculate the final result of addition or subtraction. I just want to print it all on the webpage with correct signs.
I could do so by writing 6 nested if() blocks but that seems like a lot of work and doing it every time will be error prone. Is there anything clever that I can do to output the right sign.
The easiest way would be to correct the operator appearance in the final string:
$s = '5 + -10 + 12 + -18 + 9 + - 7'; // result of interpolation or concatenation
$s = str_replace('+ -', '- ', $s);
// => "5 - 10 + 12 - 18 + 9 - 7"
If this is possible for you, this is as fast as it gets -- no looping (in php), no treating each number one at a time with a conditional. If you loop anyway, I'd recommend #Phils suggestion with array_reduce -- functional style php -- adapted to your needs.
Need to check for each variable manually like this:
echo "$a " . ($b < 0 ? " - " . abs($b) : " + $b") . ($c < 0 ? " - " . abs($c) : " + $c") . ($d < 0 ? " - " . abs($d) : " + $d") . ($e < 0 ? " - " . abs($e) : " + $e") . ($f < 0 ? " - " . abs($f) : " + $f");
you can use php sprintf function.
function formatNum($num){
return sprintf("%+d",$num);
}
or
function formatNum($num) {
$num = (int) $num; // or (float) if you'd rather
return (($num >= 0) ? '+' : '-') . $num; // implicit cast back to string
}
for more detail please read it :- http://php.net/manual/en/function.sprintf.php
try this
$a = 10;
$b=-20;
$text = $a." ".$b;
$text= str_replace(" ", "+", $text);
echo $text;
OUTPUT
10+-20
Put the numbers in an array and use array_reduce to create the string
$numbers = [5, -10, 12, -18, 9, -7];
$first = array_shift($numbers);
echo array_reduce($numbers, function($str, $num) {
return $str . sprintf(' %s %d', $num < 0 ? '-' : '+', abs($num));
}, $first);
Demo ~ https://eval.in/1034635
This way you can handle an arbitrary amount of numbers without duplicating logic everywhere.
this is the most strange thing that has ever happened to me with php
This is the code source code:
echo 'rsi_color_by_number '.$i+$di.' = rsicoloredbackground >'.$i+$di .' and rsicoloredbackground <'. $i+$di+1 ."? black:#ffffff00 \n";
and it echoes only this:
1? black:#ffffff00
The problem is operator precedence. + and . have the same precedence, and left associativity, so
'string' . $i + $di . 'string2'
is treated as
(('string' . $i) + $di) . 'string2'
This will try to use 'string' . $i as a number and add that to $di.
You can solve this with explicit parentheses:
echo 'rsi_color_by_number '.($i+$di).' = rsicoloredbackground >'.($i+$di) .' and rsicoloredbackground <'. ($i+$di+1) ."? black:#ffffff00 \n";
But when you find yourself repeating $i + $di in the code, it can be useful to assign it to a variable:
$newi = $i + $di;
echo 'rsi_color_by_number '.$newi.' = rsicoloredbackground >'.$newi.' and rsicoloredbackground <'. ($newi+1) ."? black:#ffffff00 \n";
If $i and $di are strings, try this:
echo 'rsi_color_by_number '.$i.$di.' = rsicoloredbackground >'.$i.$di .' and rsicoloredbackground <'. $i.($di+1) ."? black:#ffffff00 \n";
If $i and $di are numbers, try this:
$num = (int)$i + (int)$di;
echo "rsi_color_by_number {$num} = rsicoloredbackground > {$num} and rsicoloredbackground < ". (int)$num + 1 . "? black:#ffffff00 \n";
If that works for you, you should do calculations before your echo statement, to keep your code clean and precise and prevent against repeating the same calculation more often and making mistakes... the (int) before any variable will cast that variable as an integer; whereas before it is uncasted... Check php.net for type casting.
Without seeng what $i and $di is, it's difficult to know what you are doing.
If you don't know the values of those variables, don't forget to use var_dump
var_dump($i);
var_dump($di);
I would like to make the decimals in the following string display as superscript:
$string .= number_format(round($value, (int)$decimal_place), (int)$decimal_place, $decimal_point, $thousand_point);
I'm not very smart but I have been trying since yesterday using different methods I've found searching stack overflow. Stuff like ."<sup> or just "<sup>" and also .'<sup>' and so many other combinations, but nothing works. I either get an error or the price disappears due to the error I introduce into the code because as I said I'm not the sharpest tool in the shed.
Please check out the code I have below, this will format your string, and then use regular expressions to superscript the decimal
<?
function superscript_value($value, $prefix = '$') {
$decimal_place = 2;
$decimal_point = '.';
$thousand_point = ',';
if(round($value, 0) == $value)
return $prefix . $value;
else
return $prefix . preg_replace("/\.(\d*)/", "<sup>.$1</sup>", number_format($value, (int)$decimal_place, $decimal_point, $thousand_point));
}
echo superscript_value(123456.789, '$') . "\n";
// $123,456<sup>.79</sup>
echo superscript_value(10.00, '$') . "\n";
// $10
$123,456.79
$10
You should use HTML formatting for that:
$i = 42;
$string .= "<sup>".$i."</sup>";
It will produce something like 42.
(assume php5) consider
<?php
$foo = 'some words';
//case 1
print "these are $foo";
//case 2
print "these are {$foo}";
//case 3
print 'these are ' . $foo;
?>
Is there much of a difference between 1 and 2?
If not, what about between 1/2 and 3?
The performance difference has been irrelevant since at least January 2012, and likely earlier:
Single quotes: 0.061846971511841 seconds
Double quotes: 0.061599016189575 seconds
Earlier versions of PHP may have had a difference - I personally prefer single quotes to double quotes, so it was a convenient difference. The conclusion of the article makes an excellent point:
Never trust a statistic you didn’t forge yourself.
(Although the article quotes the phrase, the original quip was likely falsely attributed to Winston Churchill, invented by Joseph Goebbels' propaganda ministry to portray Churchill as a liar:
Ich traue keiner Statistik, die ich nicht selbst gefälscht habe.
This loosely translates to, "I do not trust a statistic that I did not fake myself.")
Well, as with all "What might be faster in real life" questions, you can't beat a real life test.
function timeFunc($function, $runs)
{
$times = array();
for ($i = 0; $i < $runs; $i++)
{
$time = microtime();
call_user_func($function);
$times[$i] = microtime() - $time;
}
return array_sum($times) / $runs;
}
function Method1()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = "these are $foo";
}
function Method2()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = "these are {$foo}";
}
function Method3()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = "these are " . $foo;
}
print timeFunc('Method1', 10) . "\n";
print timeFunc('Method2', 10) . "\n";
print timeFunc('Method3', 10) . "\n";
Give it a few runs to page everything in, then...
0.0035568
0.0035388
0.0025394
So, as expected, the interpolation are virtually identical (noise level differences, probably due to the extra characters the interpolation engine needs to handle). Straight up concatenation is about 66% of the speed, which is no great shock. The interpolation parser will look, find nothing to do, then finish with a simple internal string concat. Even if the concat were expensive, the interpolator will still have to do it, after all the work to parse out the variable and trim/copy up the original string.
Updates By Somnath:
I added Method4() to above real time logic.
function Method4()
{
$foo = 'some words';
for ($i = 0; $i < 10000; $i++)
$t = 'these are ' . $foo;
}
print timeFunc('Method4', 10) . "\n";
Results were:
0.0014739
0.0015574
0.0011955
0.001169
When you are just declaring a string only and no need to parse that string too, then why to confuse PHP debugger to parse. I hope you got my point.
Live benchmarks:
http://phpbench.com/
There is actually a subtle difference when concatenating variables with single vs double quotes.
#Adam's test used
"these are " . $foo
note that the following is even faster:
'these are ' . $foo;
this is due to the fact, that a double quoted "string" gets evaluated, where a single quoted 'string' is just taken as is...
Don't get too caught up on trying to optimize string operations in PHP. Concatenation vs. interpolation is meaningless (in real world performance) if your database queries are poorly written or you aren't using any kind of caching scheme. Write your string operations in such a way that debugging your code later will be easy, the performance differences are negligible.
#uberfuzzy Assuming this is just a question about language minutia, I suppose it's fine. I'm just trying to add to the conversation that comparing performance between single-quote, double-quote and heredoc in real world applications in meaningless when compared to the real performance sinks, such as poor database queries.
Any differences in execution time are completely negligible.
Please see
NikiC's Blog: Disproving the Single Quotes Performance Myth for a technical explanation how interpolation and concatenation works in PHP and why it is absolutely pointless to care about their speed.
Don't waste time on micro-optimizations like this. Use a profiler to measure the performance of your application in a real world scenario and then optimize where it is really needed. Optimising a single sloppy DB query is likely to make a bigger performance improvement than applying micro-optimisations all over your code.
there is a difference when concatenating variables... and what you are doing with the result... and if what you are doing is dumping it to output, is or isn't output buffering on.
also, what is the memory situation of the server? typically memory management on a higher level platform is worse than that at lower platforms...
$a = 'parse' . $this;
is managing memory at the user code platform level...
$a = "parse $this";
is managing memory at the php system code platform level...
so these benchmarks as related to CPU don't tell the full story.
running the benchmark 1000 times vs running the benchmark 1000 times on a server that is attempting to run that same simulation 1000 times concurrently... you might get drastically different results depending on the scope of the application.
I seem to remember that the developer of the forum software, Vanilla replaced all the double quotes in his code with single quotes and noticed a reasonable amount of performance increase.
I can't seem to track down a link to the discussion at the moment though.
Just to add something else to the mix, if you are using a variable inside a double quoted string syntax:
$foo = "hello {$bar}";
is faster than
$foo = "hello $bar";
and both of these are faster than
$foo = 'hello' . $bar;
Double quotes can be much slower. I read from several places that that it is better to do this
'parse me '.$i.' times'
than
"parse me $i times"
Although I'd say the second one gave you more readable code.
Practically there is no difference at all! See the timings: http://micro-optimization.com/single-vs-double-quotes
It should be noted that, when using a modified version of the example by Adam Wright with 3 variables, the results are reversed and the first two functions are actually faster, consistently. This is with PHP 7.1 on CLI:
function timeFunc($function, $runs)
{
$times = array();
for ($i = 0; $i < $runs; $i++)
{
$time = microtime();
call_user_func($function);
#$times[$i] = microtime() - $time;
}
return array_sum($times) / $runs;
}
function Method1()
{
$foo = 'some words';
$bar = 'other words';
$bas = 3;
for ($i = 0; $i < 10000; $i++)
$t = "these are $foo, $bar and $bas";
}
function Method2()
{
$foo = 'some words';
$bar = 'other words';
$bas = 3;
for ($i = 0; $i < 10000; $i++)
$t = "these are {$foo}, {$bar} and {$bas}";
}
function Method3()
{
$foo = 'some words';
$bar = 'other words';
$bas = 3;
for ($i = 0; $i < 10000; $i++)
$t = "these are " . $foo . ", " . $bar . " and " .$bas;
}
print timeFunc('Method1', 10) . "\n";
print timeFunc('Method2', 10) . "\n";
print timeFunc('Method3', 10) . "\n";
I've also tried with '3' instead of just the integer 3, but I get the same kind of results.
With $bas = 3:
0.0016254
0.0015719
0.0019806
With $bas = '3':
0.0016495
0.0015608
0.0022755
It should be noted that these results vary highly (I get variations of about 300%), but the averages seem relatively steady and almost (9 out of 10 cases) always show a faster execution for the 2 first methods, with Method 2 always being slightly faster than method 1.
In conclusion: what is true for 1 single operation (be it interpolation or concatenation) is not always true for combined operations.
Yes, originally this is about PHP5, however in few months arrive PHP8 and today the best option tested over my PHP 7.4.5 is use PHP - Nowdoc (tested over WIN 10 + Apache and CentOs 7 + Apache):
function Method6(){
$k1 = 'AAA';
for($i = 0; $i < 10000; $i ++)$t = <<<'EOF'
K1=
EOF
.$k1.
<<<'EOF'
K2=
EOF
.$k1;
}
here the method #5 (using Heredoc to concatenat):
function Method5(){
$k1 = 'AAA';
for($i = 0; $i < 10000; $i ++)$t = <<<EOF
K1= $k1
EOF
.<<<EOF
K2=$k1
EOF;
}
the methods 1 to 4 is in beginning of this post
In all my tests the "winner" is method #6 (Newdoc), no't very easy to read, but very fast in CPU and ever using the function function timeFunc($function) by #Adam Wright.
I have tested php 7.4 and php 5.4 with following test cases, It was little still confusing to me.
<?php
$start_time = microtime(true);
$result = "";
for ($i = 0; $i < 700000; $i++) {
$result .= "THE STRING APPENDED IS " . $i;
// AND $result .= 'THE STRING APPENDED IS ' . $i;
// AND $result .= "THE STRING APPENDED IS $i";
}
echo $result;
$end_time = microtime(true);
echo "<br><br>";
echo ($end_time - $start_time) . " Seconds";
PHP 7.4 Outputs
1. "THE STRING APPENDED IS " . $i = 0.16744208335876
2. 'THE STRING APPENDED IS ' . $i = 0.16724419593811
3. "THE STRING APPENDED IS $i" = 0.16815495491028
PHP 5.3 Outputs
1. "THE STRING APPENDED IS " . $i = 0.27664494514465
2. 'THE STRING APPENDED IS ' . $i = 0.27818703651428
3. "THE STRING APPENDED IS $i" = 0.28839707374573
I have tested so many times, In php 7.4 it seems to be all 3 test cases got same result many times but still concatenation have little bittle advantage in performance.
Based on #adam-wright answer, I wanted to know if speed difference happens without no concataining / no vars in a string.
== My questions...
is $array['key'] call or set faster than $array["key"] !?
is $var = "some text"; slower than $var = 'some text'; ?
== My tests with new vars every time to avoid use same memory address :
function getArrDblQuote() {
$start1 = microtime(true);
$array1 = array("key" => "value");
for ($i = 0; $i < 10000000; $i++)
$t1 = $array1["key"];
echo microtime(true) - $start1;
}
function getArrSplQuote() {
$start2 = microtime(true);
$array2 = array('key' => 'value');
for ($j = 0; $j < 10000000; $j++)
$t2 = $array2['key'];
echo microtime(true) - $start2;
}
function setArrDblQuote() {
$start3 = microtime(true);
for ($k = 0; $k < 10000000; $k++)
$array3 = array("key" => "value");
echo microtime(true) - $start3;
}
function setArrSplQuote() {
$start4 = microtime(true);
for ($l = 0; $l < 10000000; $l++)
$array4 = array('key' => 'value');
echo microtime(true) - $start4;
}
function setStrDblQuote() {
$start5 = microtime(true);
for ($m = 0; $m < 10000000; $m++)
$var1 = "value";
echo microtime(true) - $start5;
}
function setStrSplQuote() {
$start6 = microtime(true);
for ($n = 0; $n < 10000000; $n++)
$var2 = 'value';
echo microtime(true) - $start6;
}
print getArrDblQuote() . "\n<br>";
print getArrSplQuote() . "\n<br>";
print setArrDblQuote() . "\n<br>";
print setArrSplQuote() . "\n<br>";
print setStrDblQuote() . "\n<br>";
print setStrSplQuote() . "\n<br>";
== My Results :
array get double quote 2.1978828907013
array get single quote 2.0163490772247
array set double quote 1.9173440933228
array get single quote 1.4982950687408
var set double quote 1.485809803009
var set single quote 1.3026781082153
== My conclusion !
So, result is that difference is not very significant. However, on a big project, I think it can make the difference !