Function, ការលូតលាស់ និង Logarithm

មាតិកា

  1. Function គឺជាម៉ាស៊ីនពី Input ទៅ Output
  2. រូបរាងបីនៃការលូតលាស់
  3. ស្វ័យគុណ និង Exponent
  4. ហេតុអ្វីការលូតលាស់ Exponential គ្រោះថ្នាក់
  5. Logarithm៖ តើខ្ញុំអាចកាត់ពាក់កណ្តាលបានប៉ុន្មានដង?
  6. Binary Search៖ មួយក្នុងមួយលានក្នុង 20 ជំហាន
  7. Logarithm ក្នុង JavaScript
  8. ការលូតលាស់ផ្សំ និងពេលវេលាកើនទ្វេដង
  9. រូបមន្ត៖ Module growth
  10. សាកល្បងដោយខ្លួនឯង

1. Function គឺជាម៉ាស៊ីនពី Input ទៅ Output

អ្នកសរសេរ function រួចហើយ។ ក្នុងគណិតវិទ្យា function គឺជាគំនិតដូចគ្នា៖ ម៉ាស៊ីនដែលទទួល input ហើយតែងតែផ្តល់ output ដូចគ្នាសម្រាប់ input នោះ។ ដាក់ 5 ចូល ទទួលបាន 10 ចេញ។ ថ្ងៃស្អែកដាក់ 5 ចូលម្តងទៀត ក៏ទទួលបាន 10 ចេញដដែល។

function double(x) {
  return x * 2;
}

console.log(double(5)); // 10
console.log(double(0)); // 0

គណិតវិទូសរសេរវាថា f(x) = 2x អានថា "f នៃ x ស្មើ 2 គុណ x"។ x គឺ input ហើយ f(x) គឺ output។ គ្មានអ្វីលើសពីនេះទេ។

តារាង input-to-output គឺជាវិធីលឿនបំផុតដើម្បីយល់ពី function ណាមួយ។ នេះគឺ f(x) = 3x + 2៖

function f(x) {
  return 3 * x + 2;
}

console.log(f(0), f(1), f(2)); // 2 5 8

រាល់ពេល x កើនឡើង 1 output កើនឡើង 3។ ចងចាំលំនាំស្ថិរភាពបែបនោះ វាគឺជារូបរាងទីមួយក្នុងបីដែលអ្នកត្រូវស្គាល់។

ហេតុអ្វីរឿងនេះសំខាន់សម្រាប់អ្នកសរសេរកម្មវិធី? ព្រោះសំណួរ "តើការងារលូតលាស់យ៉ាងណាពេលទិន្នន័យលូតលាស់?" គឺជាសំណួរអំពី function។ Input គឺទំហំនៃទិន្នន័យរបស់អ្នក (ឧទាហរណ៍ ចំនួនអ្នកប្រើ) ហើយ output គឺបរិមាណការងារ (ពេលវេលា, ជំហាន, អង្គចងចាំ) ដែលកូដរបស់អ្នកត្រូវការ។ ជំពូកបន្ទាប់បំលែងរឿងនេះទៅជាសញ្ញា Big-O។

2. រូបរាងបីនៃការលូតលាស់

ឱ្យ n ជាទំហំនៃ input របស់អ្នក។ ប្រៀបធៀប function ងាយៗបី៖

nLinear: nQuadratic: n * nExponential: 2^n
1112
2244
3398
441616
552532
10101001,024
10010010,000ប្រហែល 1.27 x 10^30
100010001,000,000ប្រហែល 1.07 x 10^301

អ្នកអាចបោះពុម្ពតារាងនេះដោយខ្លួនឯង៖

for (const n of [1, 2, 3, 4, 5, 10, 100, 1000]) {
  console.log(n, n, n * n, 2 ** n);
}
// 10 10 100 1024
// 100 100 10000 1.2676506002282294e+30
// 1000 1000 1000000 1.0715086071862673e+301

(2 ** n គឺជា power operator របស់ JavaScript ដែលនឹងពន្យល់បន្ទាប់ ហើយ e+30 មានន័យថា "គុណ 10 ស្វ័យគុណ 30"។)

ទាំងបីចាប់ផ្តើមពីតម្លៃស្រដៀងគ្នា រួចដាច់ចេញពីគ្នា៖

  • ការលូតលាស់ Linear៖ input កើនទ្វេដង ការងារកើនទ្វេដង។ ការអានគ្រប់ជួរនៃឯកសារគឺ linear។
  • ការលូតលាស់ Quadratic៖ input កើនទ្វេដង ការងារកើន បួនដង។ ការប្រៀបធៀបអ្នកប្រើម្នាក់ៗជាមួយអ្នកប្រើផ្សេងទៀតគ្រប់គ្នាគឺ quadratic។
  • ការលូតលាស់ Exponential៖ បន្ថែម មួយ ទៅ input ហើយការងារកើនទ្វេដង។ ការសាកល្បងគ្រប់បន្សំបើក/បិទដែលអាចមានរបស់កុងតាក់ n គឺ exponential។

នៅ n = 100 ជួរ exponential មាន 31 ខ្ទង់។ គ្មានកុំព្យូទ័រណាអាចបញ្ចប់ជំហានច្រើនយ៉ាងនេះទេ។ នេះគឺជារូបភាពសំខាន់បំផុតតែមួយគត់នៃជំពូក។

3. ស្វ័យគុណ និង Exponent

ស្វ័យគុណ (power) មានន័យថាការគុណម្តងហើយម្តងទៀត។ ក្នុង 2^5 លេខ 2 គឺជា base ហើយ 5 គឺជា exponent ហើយវាមានន័យថា 2 ប្រាំដងគុណគ្នា៖

2^5 = 2 * 2 * 2 * 2 * 2 = 32

JavaScript សរសេរវាជា 2 ** 5 ឬ Math.pow(2, 5)។

console.log(2 ** 10);  // 1024
console.log(2 ** 20);  // 1048576
console.log(2 ** 30);  // 1073741824
console.log(10 ** 3);  // 1000
console.log(10 ** 6);  // 1000000

ករណីពិសេសបីដែលគួរទន្ទេញ៖

Expressionតម្លៃហេតុអ្វី
x ** 1xច្បាប់ចម្លងមួយនៃ x
x ** 01ផលគុណទទេ ដូច្នេះ 5 ** 0 គឺ 1
2 ** -10.5exponent អវិជ្ជមានមានន័យថា "មួយចែកនឹង"

អ្នកធ្លាប់ឃើញ 2^10 = 1024 ពីមុន៖ នោះគឺជា "kilo" នៃកុំព្យូទ័រ ហើយជាមូលហេតុដែល 1 KiB ស្មើ 1,024 byte។ ក៏សូមកត់សម្គាល់ 2 ** 32 = 4294967296 និង 2 ** 31 - 1 = 2147483647៖ ទាំងនេះគឺជាដែនកំណត់ integer ពី Integer, Overflow និងភាពជាក់លាក់។ រាល់ bit បន្ថែមធ្វើឱ្យចំនួនតម្លៃដែលអ្នករក្សាទុកបានកើនទ្វេដង។

ច្បាប់ងាយស្រួលមួយ៖ 2^a * 2^b = 2^(a + b)។ ឧទាហរណ៍ 2^3 * 2^4 = 8 * 16 = 128 = 2^7។ ការគុណស្វ័យគុណដែលមាន base ដូចគ្នាគឺបូក exponent។ ច្បាប់នោះគឺជាអាថ៌កំបាំងដែលធ្វើឱ្យ logarithm ដំណើរការ។

4. ហេតុអ្វីការលូតលាស់ Exponential គ្រោះថ្នាក់

ការលូតលាស់ exponential ចាប់ផ្តើមយឺតៗ ដែលជាអ្វីដែលបោកបញ្ឆោតមនុស្ស។ រូបភាពបីពីពិភពពិត៖

ក្តារអុក។ ដាក់គ្រាប់អង្ករ 1 លើប្រអប់ទីមួយ, 2 លើទីពីរ, 4 លើទីបី ទ្វេដងគ្រប់ប្រអប់។ នៅប្រអប់ទី 64 ចំនួនគឺ 2^63 ប្រហែល 9.2 x 10^18 គ្រាប់ ច្រើនជាងអង្ករដែលធ្លាប់ដាំមក។

បត់ក្រដាស។ សន្លឹកក្រដាសមួយក្រាស់ប្រហែល 0.1 មីលីម៉ែត្រ។ រាល់ការបត់ធ្វើឱ្យកម្រាស់ទ្វេដង។ បន្ទាប់ពីបត់ 42 ដង ជង់មានកម្ពស់ 0.1 * 2^42 mm ដែលប្រហែល 440,000 គីឡូម៉ែត្រ ឆ្ងាយជាងព្រះច័ន្ទ (ប្រហែល 384,000 km)៖

console.log((0.1 * 2 ** 42) / 1e6); // 439804.65111040004 (គីឡូម៉ែត្រ)

លេខសម្ងាត់។ លេខសម្ងាត់ 8 តួអក្សរដែលប្រើតែអក្សរតូចមាន 26^8 លទ្ធភាព។ ការបន្ថែមប្រវែងគឺគុណ ដូច្នេះរាល់តួអក្សរបន្ថែមធ្វើឱ្យការទាយពិបាកជាង 26 ដង៖

console.log(26 ** 8);   // 208827064576      (ប្រហែល 208 ពាន់លាន)
console.log(62 ** 8);   // 218340105584896   (អក្សរ + ខ្ទង់, ប្រហែល 218 ទ្រីលាន)

នោះជាមូលហេតុដែលលេខសម្ងាត់វែងឈ្នះលេខសម្ងាត់ខ្លី "ឆ្លាត" ហើយជាមូលហេតុដែលសំណួរសុវត្ថិភាពដែលមានចម្លើយអាចមានតែ 1,000 គឺគ្មានប្រយោជន៍។

ក្នុងកូដ ការលូតលាស់ exponential លេចឡើងក្នុង recursion ដែលហៅខ្លួនឯងពីរដង។ ឧទាហរណ៍ដ៏ល្បីគឺ Fibonacci៖

function fib(n) {
  return n < 2 ? n : fib(n - 1) + fib(n - 2);
}

console.log(fib(10)); // 55
console.log(fib(20)); // 6765
console.log(fib(30)); // 832040

វាដំណើរការ ប៉ុន្តែរាល់ការហៅបង្កើតការហៅពីរទៀត។ fib(20) ធ្វើការហៅ 21,891 ដង, fib(25) ធ្វើ 242,785 ហើយ fib(30) ធ្វើ 2,692,537។ រាល់ +5 ក្នុង input គុណការងារប្រហែល 11។ សាកល្បង fib(45) ហើយ terminal របស់អ្នកនឹងគាំងយូរ។

ច្បាប់ជាក់ស្តែង៖ កូដ linear និង quadratic អាចសង្គ្រោះបានដោយផ្នែករឹងប្រសើរជាង។ កូដ exponential មិនអាចទេ។ អ្នកត្រូវផ្លាស់ប្តូរ algorithm។

5. Logarithm៖ តើខ្ញុំអាចកាត់ពាក់កណ្តាលបានប៉ុន្មានដង?

Logarithm គឺជាផ្ទុយនៃស្វ័យគុណ។ ស្វ័យគុណសួរថា "តើខ្ញុំទទួលបានអ្វីបើគុណ 2 នឹងខ្លួនឯង 10 ដង?" ហើយចម្លើយគឺ 1024។ Logarithm សួរបញ្ច្រាស់៖ "តើខ្ញុំត្រូវគុណ 2 ប៉ុន្មានដងដើម្បីទៅដល់ 1024?" ហើយចម្លើយគឺ 10។

2^10 = 1024     <=>     log2(1024) = 10

អាន log2(1024) ថា "log base 2 នៃ 1024"។ លេខ 2 តូចគឺជា base ហើយចម្លើយគឺជា exponent។

នេះគឺជាវិធីគិតដែលងាយបំផុត៖ log2(n) គឺប្រហែលជាចំនួនដងដែលអ្នកអាចកាត់ n ជាពាក់កណ្តាលមុននឹងទៅដល់ 1។ ចាប់ផ្តើមពី 1,000 ធាតុ ហើយបន្តកាត់ពាក់កណ្តាល៖

1000 -> 500 -> 250 -> 125 -> 62 -> 31 -> 15 -> 7 -> 3 -> 1

នោះគឺ 9 ដងនៃការកាត់ពាក់កណ្តាល ហើយ log2(1000) គឺប្រហែល 9.97។ ជិតគ្នា ហើយភាពខុសគ្នាគ្រាន់តែជាការបង្គត់ប្រភាគ។

Base ផ្សេងៗដំណើរការដូចគ្នា៖

Expressionអត្ថន័យតម្លៃ
log2(8)2 គុណអ្វីបាន 8? 2^33
log10(1000)10^3 = 10003
log3(81)3^4 = 814
log5(125)5^3 = 1253

ព្រោះ log10(n) រាប់ប្រហែល ខ្ទង់ របស់ n ហើយ log2(n) រាប់ប្រហែល bit របស់ n logarithm លូតលាស់យឺតគួរឱ្យភ្ញាក់ផ្អើល៖

nlog2(n)
1,000ប្រហែល 10
1,000,000ប្រហែល 20
1,000,000,000ប្រហែល 30
1,000,000,000,000ប្រហែល 40

ការគុណ input នឹង 1,000 បន្ថែមតែ 10 ទៅចម្លើយ។ algorithm logarithmic ស្ទើរតែមិនកត់សម្គាល់ថា input របស់វាធំប៉ុនណាទេ ហើយនោះជាអ្វីដែលធ្វើឱ្យ logarithm មានតម្លៃខ្លាំងសម្រាប់អ្នកសរសេរកម្មវិធី។

6. Binary Search៖ មួយក្នុងមួយលានក្នុង 20 ជំហាន

នេះគឺជាកន្លែងដែល logarithm រកស៊ីចិញ្ចឹមជីវិត។ ឧបមាថាខ្ញុំជ្រើសលេខសម្ងាត់ពី 1 ដល់ 1,000,000 ហើយអ្នកត្រូវទាយវា។ បន្ទាប់ពីការទាយនីមួយៗ ខ្ញុំប្រាប់ថា "ខ្ពស់ជាង" ឬ "ទាបជាង"។

យុទ្ធសាស្ត្រ linear (ទាយ 1 បន្ទាប់មក 2 បន្ទាប់មក 3...) អាចត្រូវទាយមួយលានដង។ យុទ្ធសាស្ត្រឆ្លាតគឺ ទាយចំកណ្តាល រាល់ពេល៖

  • ទាយ 500,000។ ប្រសិនបើ "ទាបជាង" អ្នកទើបតែលុបបំបាត់ពាក់កណ្តាលនៃលទ្ធភាពទាំងអស់។
  • ទាយ 250,000 ហើយម្តងទៀតពាក់កណ្តាលនៃអ្វីដែលនៅសល់បាត់ទៅ។
  • បន្តទៅមុខ។ រាល់ការទាយធ្វើឱ្យ pool ថយពាក់កណ្តាល។

Pool រួមតូចដូច 1,000,000 -> 500,000 -> 250,000 -> ... -> 1។ តើនោះជាការកាត់ពាក់កណ្តាលប៉ុន្មានដង? 2^20 = 1,048,576 ដែលនៅលើមួយលានបន្តិច ដូច្នេះ ទាយ 20 ដងគឺគ្រប់គ្រាន់ជានិច្ច។ សម្រាប់ធាតុមួយ ពាន់លាន គឺមានតែ 30។

យុទ្ធសាស្ត្រនេះហៅថា binary search។ វាតម្រូវឱ្យទិន្នន័យ តម្រៀបរួច (sorted) (ដើម្បីឱ្យ "ខ្ពស់ជាង" និង "ទាបជាង" មានន័យ) ដូចជាសៀវភៅទូរស័ព្ទ, វចនានុក្រម ឬ array នៃ ID ដែលតម្រៀបរួច។ នេះជាកំណែដែលដំណើរការ៖

function binarySearch(sorted, target) {
  let low = 0;
  let high = sorted.length - 1;
  while (low <= high) {
    const mid = Math.floor((low + high) / 2);
    if (sorted[mid] === target) return mid;
    if (sorted[mid] < target) low = mid + 1;
    else high = mid - 1;
  }
  return -1;
}

const ids = Array.from({ length: 1_000_000 }, (_, i) => i * 2);
console.log(binarySearch(ids, 1999998)); // 999999
console.log(binarySearch(ids, 7));       // -1

low និង high សម្គាល់ផ្នែកនៃ array ដែលនៅក្នុងល្បែង។ រាល់ loop មើលកណ្តាល (mid) បន្ទាប់មកបោះចោលពាក់កណ្តាលដែលមិនអាចមាន target។ Math.floor បង្គត់ចុះ ដូច្នេះ mid ជា index ទាំងមូល ហើយ function ត្រឡប់ -1 ពេលរកមិនឃើញធាតុ។ សញ្ញា underscore ក្នុង 1_000_000 គ្រាន់តែជាជំនួយឱ្យងាយអានលេខធំៗ។

Loop ធម្មតាអាចពិនិត្យធាតុរហូតដល់មួយលាន ចំណែកនេះពិនិត្យប្រហែល 20។ អ្នកនឹងប្រណាំងទាំងពីរឱ្យបានត្រឹមត្រូវនៅក្នុង សញ្ញា Big-O។

7. Logarithm ក្នុង JavaScript

JavaScript ផ្តល់ function logarithm បីដល់អ្នក៖

console.log(Math.log2(1024));   // 10
console.log(Math.log10(1000));  // 3
console.log(Math.log(Math.E));  // 1   (natural log, base e = 2.718...)

Math.log គឺជា natural logarithm ដែលមាន base e (ថេរពិសេសមួយ ប្រហែល 2.71828 ដែលលេចឡើងក្នុងការលូតលាស់ និងការរលាយ)។ អ្នកកម្រត្រូវការវាដោយផ្ទាល់ ប៉ុន្តែវាផ្តល់ជាមធ្យោបាយគណនា log ក្នុង base ណាមួយ។ ច្បាប់ change of base ថា៖

log_b(x) = ln(x) / ln(b)
function logBase(base, x) {
  return Math.log(x) / Math.log(base);
}

console.log(logBase(2, 1024));  // 10
console.log(logBase(5, 125));   // 3.0000000000000004
console.log(logBase(3, 81));    // 4.000000000000001
console.log(logBase(10, 1000)); // 2.9999999999999996

មើលឱ្យជិត៖ ចម្លើយគឺ ស្ទើរតែ ជាចំនួនគត់ មិនជាក់លាក់ទេ។ នេះគឺជាបញ្ហា floating-point ពីជំពូកមុនដែលលេចឡើងម្តងទៀត។ ពេលណាចម្លើយពិតគួរជា integer ត្រូវបង្គត់វា ឬប្រៀបធៀបដោយ tolerance (nearlyEqual)។ ពេលអាចធ្វើបាន សូមប្រើ Math.log2 និង Math.log10 ដែលមានសម្រាប់ជាក់លាក់។

ការពិតពីរទៀតដែលត្រូវចងចាំ៖

console.log(Math.log(0));  // -Infinity
console.log(Math.log(-1)); // NaN

អ្នកអាចយក log បានតែនៃលេខវិជ្ជមានប៉ុណ្ណោះ។ ហើយចំនួនទាយអតិបរមាដែល binary search ត្រូវការសម្រាប់ n ធាតុគឺ Math.ceil(Math.log2(n + 1))៖

console.log(Math.ceil(Math.log2(1_000_000 + 1))); // 20
console.log(Math.ceil(Math.log2(1000 + 1)));      // 10

Math.ceil បង្គត់ ឡើង ព្រោះប្រភាគនៃការទាយមួយនៅតែត្រូវចំណាយការទាយទាំងមូលមួយ។

8. ការលូតលាស់ផ្សំ និងពេលវេលាកើនទ្វេដង

ការលូតលាស់ exponential មិនមែនគ្រាន់តែជាគ្រោះថ្នាក់ទេ វាក៏ជារបៀបដែលលុយលូតលាស់ដែរ។ ឧបមាថាអ្នកដាក់ $1,000 ក្នុងគណនីសន្សំដែលបង់ 7% ក្នុងមួយឆ្នាំ។ រាល់ឆ្នាំសមតុល្យត្រូវគុណនឹង 1.07 (ដើមបូក 7%)។ បន្ទាប់ពី y ឆ្នាំ៖

balance = principal * (1 + rate) ^ years

នេះគឺជា ការលូតលាស់ផ្សំ (compound growth) ព្រោះការប្រាក់នៃឆ្នាំនីមួយៗក៏រកការប្រាក់ដែរ។ ក្នុង JavaScript៖

function compound(principal, ratePercent, years) {
  return principal * (1 + ratePercent / 100) ** years;
}

for (const y of [0, 5, 10, 20, 30]) {
  console.log(y, compound(1000, 7, y).toFixed(2));
}
// 0 1000.00
// 5 1402.55
// 10 1967.15
// 20 3869.68
// 30 7612.26

10 ឆ្នាំដំបូងបន្ថែមប្រហែល $967 ហើយ 10 ឆ្នាំចុងក្រោយបន្ថែមប្រហែល $3,743។ អត្រាដូចគ្នា ប៉ុន្តែ base ធំជាង៖ ខ្សែកោងកោងឡើងលើ។ វាគឺជារូបភាពដូចជួរ 2^n ដែរ គ្រាន់តែមាន base ទន់ភ្លន់ជាង 1.07។

ឥឡូវសំណួរ "តើត្រូវប្រើពេលប៉ុន្មានទើបលុយរបស់ខ្ញុំកើនទ្វេដង?" គឺជា logarithm៖ តើត្រូវគុណនឹង 1.07 ប៉ុន្មានដងដើម្បីទៅដល់ 2? ចម្លើយគឺ log(2) / log(1.07)៖

function doublingTime(ratePercent) {
  return Math.log(2) / Math.log(1 + ratePercent / 100);
}

console.log(doublingTime(7).toFixed(2));  // 10.24
console.log(doublingTime(1).toFixed(2));  // 69.66
console.log(doublingTime(10).toFixed(2)); // 7.27

ត្រង់ 7% លុយរបស់អ្នកកើនទ្វេដងក្នុងរយៈពេលប្រហែល 10.2 ឆ្នាំ។ មនុស្សប្រើ ច្បាប់ 72 (rule of 72) ជាផ្លូវកាត់ក្នុងចិត្ត៖ យក 72 ចែកនឹងអត្រា។ 72 / 7 គឺប្រហែល 10.3 ជិតនឹងចម្លើយពិតណាស់។

គណិតវិទ្យាដូចគ្នាពិពណ៌នាអ្វីដែលលូតលាស់ក្នុងប្រព័ន្ធ របស់អ្នក៖ សេវាកម្មដែលចរាចរណ៍កើន 5% រៀងរាល់សប្តាហ៍នឹងកើនទ្វេដងក្នុងរយៈពេលប្រហែល 14 សប្តាហ៍ មូលដ្ឋានទិន្នន័យដែលកើន 10% ក្នុងមួយខែនឹងកើនទ្វេដងក្នុងរយៈពេលប្រហែល 7 ខែ។ ការគិតតាមពេលវេលាកើនទ្វេដងជួយអ្នកឆ្លើយសំណួរ "តើយើងនឹងអស់ disk ឬ capacity ពេលណា?" មុននឹងវាក្លាយជាអាសន្ន។

ហើយវាក៏ដំណើរការបញ្ច្រាសដែរ។ បំណុលដែលមានអត្រាការប្រាក់ខ្ពស់ ឬ bug រីករាលដាលដែលធ្វើឱ្យរបាយការណ៍កំហុសកើនទ្វេដងរាល់ម៉ោង គឺជាការលូតលាស់ exponential ដែលអ្នកមិនចង់បាន។

9. រូបមន្ត៖ Module growth

បន្ថែមឧបករណ៍របស់ជំពូកនេះទៅ mathlab។ បង្កើត src/growth.js៖

// src/growth.js

// ចំនួនទាយអាក្រក់បំផុតដែល binary search ត្រូវការសម្រាប់ n ធាតុដែលតម្រៀបរួច។
export function stepsToBinarySearch(n) {
  return Math.ceil(Math.log2(n + 1));
}

// Logarithm នៃ x ក្នុង base ណាមួយ (អាចខុសបន្តិចដោយសារកំហុស float)។
export function logBase(base, x) {
  return Math.log(x) / Math.log(base);
}

// ឆ្នាំ (ឬរយៈពេល) ដើម្បីឱ្យអ្វីមួយដែលលូតលាស់ក្នុងអត្រា ratePercent កើនទ្វេដង។
export function doublingTime(ratePercent) {
  return Math.log(2) / Math.log(1 + ratePercent / 100);
}

// តម្លៃបន្ទាប់ពីផ្សំ principal ក្នុងអត្រា ratePercent សម្រាប់ចំនួនឆ្នាំមួយ។
export function compound(principal, ratePercent, years) {
  return principal * (1 + ratePercent / 100) ** years;
}

Re-export វាពី src/index.js៖

export * from "./growth.js";

បន្ថែមកូដនេះទៅ demo.js ហើយដំណើរការ node demo.js៖

import {
  stepsToBinarySearch, logBase, doublingTime, compound,
} from "./src/growth.js";

console.log("--- growth ---");
console.log(stepsToBinarySearch(1000));          // 10
console.log(stepsToBinarySearch(1_000_000));     // 20
console.log(stepsToBinarySearch(1_000_000_000)); // 30
console.log(logBase(2, 1024));                   // 10
console.log(logBase(3, 81));                     // 4.000000000000001
console.log(doublingTime(7).toFixed(2));         // 10.24
console.log(compound(1000, 7, 10).toFixed(2));   // 1967.15

សូមកត់សម្គាល់ថា logBase(3, 81) មិនមែនជា 4 យ៉ាងជាក់លាក់ទេ។ នោះគឺជារឿងរំពឹងទុក ហើយជាការរំលឹកល្អឱ្យបង្គត់មុនបង្ហាញលទ្ធផលដល់អ្នកប្រើ។

10. សាកល្បងដោយខ្លួនឯង

  1. បង្កើតតារាងការលូតលាស់។ សរសេរ loop សម្រាប់ n ពី 1 ដល់ 10 ដែលបោះពុម្ព n, n * n, n ** 3 និង 2 ** n លើបន្ទាត់មួយ។ តើនៅ n ប៉ុន្មានដែល 2 ** n ឈ្នះ n ** 3 ជាលើកដំបូង? (ពិនិត្យចម្លើយរបស់អ្នកជាមួយ output។)
  2. រាប់ការកាត់ពាក់កណ្តាល។ សរសេរ halvings(n) ដែលធ្វើ n = Math.floor(n / 2) ម្តងហើយម្តងទៀតរហូត n ជា 1 ដោយរាប់ជំហាន។ សាកល្បងជាមួយ 1024 និង 1000000។ ប្រៀបធៀបជាមួយ Math.log2(n)។ ហេតុអ្វី 1000000 ផ្តល់ 19 នៅទីនេះ ប៉ុន្តែ binary search ត្រូវការទាយ 20 ដង?
  3. បញ្ហាបត់ក្រដាស។ តើត្រូវបត់សន្លឹកក្រដាស 0.1 mm ប៉ុន្មានដងដើម្បីលើសកម្ពស់ប្រាសាទអង្គរវត្ត (ប្រហែល 65 ម៉ែត្រ)? ប្រើ loop បន្ទាប់មកបញ្ជាក់ដោយ Math.ceil(Math.log2(65 / 0.0001))។
  4. កម្លាំងលេខសម្ងាត់។ សរសេរ passwordSpace(alphabetSize, length) ដោយប្រើ **។ ប្រៀបធៀបអក្សរតូច 8 តួ (26), អក្សរតូចធំលាយខ្ទង់ 8 តួ (62) និងអក្សរតូច 12 តួ។ មួយណាធំជាង?
  5. តើយើងនឹងអស់ពេលណា? disk មួយមានទំហំទំនេរ 500 GB ហើយទិន្នន័យរបស់អ្នកកើន 8% ក្នុងមួយខែ និងប្រើ 100 GB ឥឡូវនេះ។ ដោយប្រើ compound រកខែដំបូងដែលទិន្នន័យលើស 500 GB។ (ជំនួយ៖ loop តាមខែ ឬគណនា Math.log(5) / Math.log(1.08)។)
  6. ធ្វើឱ្យ fib ខូច។ វាស់ពេល fib(30) និង fib(35) ដោយ console.time។ តើពេលវេលាកើនប្រហែលប៉ុន្មានដង? តើនោះបង្ហាញអ្វីអំពី fib(50)?

បន្ទាប់ យើងនឹងដាក់ឈ្មោះឱ្យវាក្យសព្ទការលូតលាស់នេះ ដែលអ្នកសរសេរកម្មវិធីគ្រប់គ្នាប្រើ ហើយរៀនអានរង្វិលជុំ (loop) ជ្រៅៗក្នុងមួយភ្លែតក្នុង សញ្ញា Big-O។

ទិញកាហ្វេជូនខ្ញុំ

ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!