PHP-ում անպետք զանգվածների օպտիմալացում

Ենթադրենք, որ ինչ-որ ծրագրավորողի առջև խնդիր է դրված գտնել ամբողջ թվերի գումարը 1-ից մինչև 100000000:

Մեր ծրագրավորողը գրել է այս խնդրի նրբագեղ լուծումը, ահա այսպես.

php<?php
  echo array_sum(range(1, 100000000));
?>

Գեղեցիկ լուծում, չէ՞: Մի տողով և այդ ամենը: Բայց այն չի աշխատում: Փորձեք գործարկել այս կոդը, և այն էկրանին կնետի սխալ այն մասին, որ դուք չափազանց շատ օպերատիվ հիշողություն եք պահանջել:

Հմ, 100000000-ը կարծես այնքան էլ շատ չէ՞: Թե՞ շատ է: Եկեք հաշվենք: range ֆունկցիան ստեղծում է 100000000 թվերից բաղկացած զանգված: Ենթադրենք, որ PHP-ն թվի համար հատկացնում է 2 բայթ - ապա մեր զանգվածը պահելու համար կպահանջվի 200000000 բայթ, այսինքն՝ մոտավորապես 200 մեգաբայթ օպերատիվ հիշողություն:

Բայց իրականում կպահանջվի շատ ավելի շատ օպերատիվ հիշողություն այն պատճառով, որ PHP-ում զանգվածը պահելիս առկա են շատ մեծ լրացուցիչ ծախսեր: Օրինակ, իմ տեքստում սխալը ասում է, որ ես փորձում եմ հատկացնել 4294967304 բայթ - այսինքն՝ մոտ 4 գիգաբայթ:

Հիմա հասկանալի է, թե ինչու է առաջանում սխալ - մենք շատ հեռու անցանք թույլատրելի հիշողության սահմանաչափից:

Ոչ այնքան դժվար է մեր սկրիպտը վերագրել այլ կերպ, գործնականում օպերատիվ հիշողություն չսպառող տարբերակով.

php<?php
  $sum = 0;
  
  for ($i = 1; $i <= 100000000; $i++) {
    $sum += $i;
  }
  
  echo $sum;
?>

Կամ էլ ավելի լավ է օգտագործել մաթեմատիկական լուծում.

php<?php
  $n = 1000000;
  $sum = $n * ($n + 1) / 2;
  echo $sum;
?>
Задание 1

Ինչ-որ ծրագրավորողի առջև խնդիր էր դրված գտնել տրված թվի ֆակտորիալը: Նա այն լուծել է հետևյալ կերպ.

php<?php
  $n = 100;
  echo array_product(range(1, $n));
?>

Բացատրեք, թե ինչն է սխալ այս կոդում: Վերափոխեք կոդը դեպի ավելի օպտիմալ:

Задание 2

Ինչ-որ ծրագրավորողի առջև խնդիր էր դրված գտնել այն թվանշանների քանակը, որոնց միջոցով կարելի է գրել բոլոր ամբողջ թվերը 1-ից մինչև 1000000: Նա այն լուծել է հետևյալ կերպ.

php<?php
  echo strlen(implode('', range(1, 1000000)));
?>

Բացատրեք, թե ինչն է սխալ այս կոդում: Վերափոխեք կոդը դեպի ավելի օպտիմալ:

Задание 3

Ինչ-որ ծրագրավորողի առջև խնդիր էր դրված գտնել 7-ի վրա առանց մնացորդի բաժանվող թվերի քանակը, որոնք գտնվում են տրված միջակայքում: Նա այն լուծել է հետևյալ կերպ.

php<?php
  $arr = [];
  
  for ($i = 0; $i <= 1000; $i++) {
    if ($i % 7 == 0) {
      $arr[] = $i;
    }
  }
  
  echo count($arr);
?>

Բացատրեք, թե ինչն է սխալ այս կոդում: Վերափոխեք կոդը դեպի ավելի օպտիմալ:

Задание 4

Ինչ-որ ծրագրավորողի առջև խնդիր էր դրված գտնել թվի բաժանարարների գումարը: Նա այն լուծել է հետևյալ կերպ.

php<?php
  $num = 320;
  $divs = [];
  
  for ($i = 0; $i <= $num; $i++) {
    if ($num % $i == 0) {
      $divs[] = $i;
    }
  }
  
  echo array_sum($divs);
?>

Բացատրեք, թե ինչն է սխալ այս կոդում: Վերափոխեք կոդը դեպի ավելի օպտիմալ: