នព្វន្ត Modular
មាតិកា
- គណិតវិទ្យាដែលវិលជុំ
- Remainder និងការចែក
- លេខគូ លេខសេស និងធាតុរៀងរាល់ទី N
- អន្ទាក់លេខអវិជ្ជមាន
- Carousel និង Circular Buffer
- នាឡិកា និងថ្ងៃក្នុងសប្តាហ៍
- Hash Bucket
- Check Digit និងក្បួនដោះស្រាយ Luhn
- រូបមន្ត៖ modular.js សម្រាប់ mathlab
- សាកល្បងដោយខ្លួនឯង
1. គណិតវិទ្យាដែលវិលជុំ
ប្រសិនបើម៉ោង 10 ហើយអ្នករង់ចាំ 5 ម៉ោង វាមិនមែនម៉ោង 15 លើនាឡិកា 12 ម៉ោងទេ។ វាគឺម៉ោង 3។ លេខ វិលជុំ បន្ទាប់ពីដល់ 12។ គណិតវិទូហៅរឿងនេះថា នព្វន្ត modular ហើយ % គឺជា operator ដែលធ្វើវា។
អ្នកបានស្គាល់ % ជា operator "remainder" រួចហើយ។ នៅក្នុងជំពូកនេះ អ្នកនឹងឃើញថានិមិត្តសញ្ញាតូចមួយនេះជំរុញអ្វីខ្លះ៖
- carousel និងប៊ូតុង "បន្ទាប់/មុន" ដែលវិលជុំ
- ជួរតារាងដែលមានឆ្នូតដូចសេះបង្ក្រា (zebra)
- ថ្ងៃក្នុងសប្តាហ៍ និងម៉ោងលើនាឡិកា
- bucket នៅក្នុង hash table (ហើយដូច្នេះនៅក្នុងគ្រប់
SetនិងMap) - check digit លើកាតធនាគារដែលចាប់កំហុសវាយខុស
វាក៏លាក់អន្ទាក់អាក្រក់មួយដែរ ដែលគ្របដណ្តប់ក្នុងផ្នែកទី 4។ អ្នកអភិវឌ្ឍន៍ភាគច្រើនជួបវាម្តង នៅលើ production នៅព្រឹកថ្ងៃច័ន្ទ។
2. Remainder និងការចែក
ចាំការចែកវែងពីសាលា៖ 17 ÷ 5 = 3 ជាមួយ 2 នៅសល់។ 3 គឺ quotient (ផលចែក) ហើយ 2 គឺ remainder (សំណល់)។ ក្នុង JavaScript៖
console.log(Math.floor(17 / 5)); // 3 (quotient)
console.log(17 % 5); // 2 (remainder)
ទាំងពីរតែងតែត្រូវគ្នា៖ 5 × 3 + 2 = 17។ ជាទូទៅ៖
dividend = divisor × quotient + remainder
Remainder តែងតែតូចជាង divisor ដូច្នេះ n % 5 អាចផ្តល់បានតែ 0, 1, 2, 3, ឬ 4។ នោះគឺជាអាថ៌កំបាំងនៃការវិលជុំ៖ មិនថា n កើនធំប៉ុនណា n % 5 តែងតែធ្លាក់ក្នុងដែនតូចនោះ ហើយវាវិលតាមលំដាប់នៅពេល n កើនឡើង៖
| n | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 |
|---|---|---|---|---|---|---|---|---|---|---|---|
n % 5 | 0 | 1 | 2 | 3 | 4 | 0 | 1 | 2 | 3 | 4 | 0 |
នៅពេល n % 5 ជា 0 នោះ n ចែកដាច់នឹង 5។ យើងនិយាយថា n ជា ពហុគុណ នៃ 5 ឬ 5 ចែកដាច់ n។
ឧទាហរណ៍ពិត៖ វីដេអូមួយមានរយៈពេល 130 វិនាទី។ តើ player គួរបង្ហាញវាយ៉ាងដូចម្តេច?
const total = 130;
console.log(Math.floor(total / 60)); // 2 minutes
console.log(total % 60); // 10 seconds
នោះគឺ "2:10"។ ការចែកផ្តល់ឯកតាធំ remainder ផ្តល់អ្វីដែលនៅសល់។ លំនាំដូចគ្នាបំប្លែងធាតុ 47 ទៅជាទំព័រ៖ Math.floor(47 / 10) គឺទំព័រទី 4 (រាប់ពី 0) ហើយ 47 % 10 គឺ slot ទី 7 លើទំព័រនោះ។
3. លេខគូ លេខសេស និងធាតុរៀងរាល់ទី N
សំណួរ modular ដែលសាមញ្ញបំផុតគឺ "គូ ឬសេស?" ដែលជា "តើ n % 2 ជាអ្វី?"៖
console.log(10 % 2); // 0 -> គូ
console.log(7 % 2); // 1 -> សេស
លេខគូទុក remainder 0។ លេខសេសទុក 1។ ដូច្នេះការដាក់ឆ្នូតតារាងដោយប្រើលេខជួរ 0, 1, 2, ... គឺជាមួយបន្ទាត់៖
const rows = [0, 1, 2, 3].map((r) => (r % 2 === 0 ? "light" : "dark"));
console.log(rows); // [ 'light', 'dark', 'light', 'dark' ]
ជំនួស 2 ដោយលេខណាមួយ ដើម្បីបាន "រៀងរាល់ទី N"៖
// បង្ហាញការផ្សាយពាណិជ្ជកម្មបន្ទាប់ពីប្រកាសទី 5 រៀងរាល់ពេល
for (let post = 1; post <= 12; post++) {
if (post % 5 === 0) console.log(`ad after post ${post}`);
}
// ad after post 5
// ad after post 10
Round-robin ដំណើរការតាមរបៀបដូចគ្នា។ Server បីចែករំលែកសំណើតាមវេន ហើយសំណើលេខ n ទៅ server n % 3៖
const servers = ["s1", "s2", "s3"];
console.log([0, 1, 2, 3, 4].map((n) => servers[n % 3]));
// [ 's1', 's2', 's3', 's1', 's2' ]
4. អន្ទាក់លេខអវិជ្ជមាន
ឥឡូវនេះអន្ទាក់។ សាកល្បង % ជាមួយលេខអវិជ្ជមាន៖
console.log(-1 % 5); // -1 (!)
console.log(-7 % 5); // -2
អ្នកប្រហែលជារំពឹង 4 ព្រោះលើនាឡិកាដែលមាន 5 ទីតាំង ការថយក្រោយមួយជំហានពី 0 ធ្លាក់លើ 4។ ប៉ុន្តែ % របស់ JavaScript ផ្តល់ -1។
មូលហេតុ៖ % គឺជា operator remainder មិនមែន operator modulo ទេ។ ទាំងពីរត្រូវគ្នាសម្រាប់លេខវិជ្ជមាន ហើយមិនត្រូវគ្នាសម្រាប់លេខអវិជ្ជមាន។ Remainder របស់ JavaScript រក្សា សញ្ញានៃលេខខាងឆ្វេង ដូច្នេះលេខអវិជ្ជមានចូលផ្តល់លេខអវិជ្ជមាន (ឬសូន្យ) ចេញ។
| Expression | % របស់ JavaScript | Modulo ពិត (អ្វីដែលនាឡិកាធ្វើ) |
|---|---|---|
7 % 5 | 2 | 2 |
-7 % 5 | -2 | 3 |
-1 % 5 | -1 | 4 |
-5 % 5 | -0 | 0 |
តើវាខាំនៅឯណា? គ្រប់ទីកន្លែងដែល index អាចធ្លាក់ ចុះ៖ ប៊ូតុង "មុន" ដែលធ្វើ (index - 1) % length នឹងផលិត -1 នៅពេល index ជា 0 ហើយ slides[-1] គឺ undefined។ Carousel ទទេ។ ដំណោះស្រាយគឺ function តូចមួយដែលតែងតែត្រឡប់លេខពី 0 ដល់ m - 1៖
function mod(n, m) {
return ((n % m) + m) % m;
}
console.log(mod(-1, 5)); // 4
console.log(mod(-7, 5)); // 3
console.log(mod(7, 5)); // 2
console.log(mod(10, 5)); // 0
ហេតុអ្វីវាដំណើរការ? មួយជំហានម្តងៗជាមួយ n = -7 និង m = 5៖
n % mគឺ-2៖ ក្នុងដែនពី-(m - 1)ដល់m - 1។- បូក
m៖-2 + 5 = 3។ ឥឡូវតម្លៃមិនដែលអវិជ្ជមានទេ (តូចបំផុតដែលអាចមានគឺ-(m - 1) + m = 1ហើយ input វិជ្ជមានមានតែកើនធំឡើង)។ - យក
% mម្តងទៀត៖3 % 5 = 3។%ទីពីរនេះដោះស្រាយ input ដែលវិជ្ជមានរួចហើយ ដូចជា7 % 5 = 2បន្ទាប់មក2 + 5 = 7រួច7 % 5 = 2។
ចំណុចប្រុងប្រយ័ត្នមួយ៖ m ត្រូវតែវិជ្ជមាន។ mod(5, 0) ផ្តល់ NaN ព្រោះការចែកនឹងសូន្យគ្មាន remainder។
5. Carousel និង Circular Buffer
Carousel បង្ហាញស្លាយ i ក្នុងចំណោមស្លាយ length។ "បន្ទាប់" បូកមួយ ហើយ "មុន" ដកមួយ ហើយទាំងពីរវិលជុំនៅចុងទាំងសងខាង។ ជាមួយ mod៖
function nextIndex(i, length) {
return mod(i + 1, length);
}
function prevIndex(i, length) {
return mod(i - 1, length);
}
console.log(nextIndex(4, 5)); // 0 (ស្លាយចុងក្រោយ បន្ទាប់ទៅដំបូង)
console.log(prevIndex(0, 5)); // 4 (ស្លាយដំបូង មុនទៅចុងក្រោយ)
គ្មានប្រយោគ if គ្មានករណីពិសេស។ នោះគឺជាភាពស្រស់ស្អាតនៃនព្វន្ត modular៖ "edge case" បាត់ទៅក្នុងរូបមន្ត។
ល្បិចដូចគ្នាបង្កើត circular buffer (ហៅថា ring buffer ផងដែរ)៖ បញ្ជីទំហំថេរដែលរក្សាតែធាតុថ្មីៗបំផុត ដូចជាសារ log 3 ចុងក្រោយ។ នៅពេលវាពេញ ធាតុថ្មីសរសេរជាន់ធាតុចាស់បំផុត។
class Ring {
constructor(capacity) {
this.items = new Array(capacity);
this.start = 0; // index នៃធាតុចាស់បំផុត
this.size = 0;
}
push(item) {
const slot = (this.start + this.size) % this.items.length;
if (this.size < this.items.length) {
this.size++;
} else {
this.start = (this.start + 1) % this.items.length; // ទម្លាក់ធាតុចាស់បំផុត
}
this.items[slot] = item;
}
toArray() {
return Array.from(
{ length: this.size },
(_, k) => this.items[(this.start + k) % this.items.length],
);
}
}
const recent = new Ring(3);
for (const n of [1, 2, 3, 4, 5]) recent.push(n);
console.log(recent.toArray()); // [ 3, 4, 5 ]
ជំនួសឲ្យការរុញគ្រប់ធាតុទៅឆ្វេងរាល់ពេល (ដែលចំណាយច្រើនជាងមុនពេលបញ្ជីកាន់តែធំ) buffer គ្រាន់តែផ្លាស់ទី index ពីរជុំវិញ loop មួយ។ Audio player, network buffer និងអេក្រង់ "ប្រវត្តិ undo" ប្រើគំនិតនេះ។
ពេលខ្លះអ្នកចង់វិលជុំចូលក្នុងដែនដែលមិនចាប់ផ្តើមពី 0 ដូចជាខែ 1..12។ ផ្លាស់ចុះ វិលជុំ ផ្លាស់ត្រឡប់វិញ៖
function wrap(n, min, max) {
return min + mod(n - min, max - min + 1);
}
console.log(wrap(13, 1, 12)); // 1 (ខែទី 13 គឺខែមករា)
console.log(wrap(0, 1, 12)); // 12 (ខែទី 0 គឺខែធ្នូ)
6. នាឡិកា និងថ្ងៃក្នុងសប្តាហ៍
នព្វន្តនាឡិកាគឺជានព្វន្ត modular ដើមដំបូង។ បីម៉ោងបន្ទាប់ពីម៉ោង 11 លើនាឡិកា 12 ម៉ោង៖
console.log((11 + 3) % 12); // 2
សម្រាប់ម៉ោងលើនាឡិកា 24 ម៉ោង ជាមួយការជួសជុលសម្រាប់ការថយក្រោយ សូមប្រើ mod ពីខាងលើ៖
const pad = (n) => String(n).padStart(2, "0");
console.log(pad(mod(22 + 5, 24))); // "03" (5 ម៉ោងបន្ទាប់ពី 22:00)
console.log(pad(mod(2 - 5, 24))); // "21" (5 ម៉ោងមុន 02:00)
ថ្ងៃក្នុងសប្តាហ៍គឺជា loop នៃ 7។ ដាក់លេខ 0 សម្រាប់ថ្ងៃអាទិត្យ ដល់ 6 សម្រាប់ថ្ងៃសៅរ៍ ដែលជាអ្វីដែល getDay() របស់ JavaScript ធ្វើយ៉ាងពិតប្រាកដ៖
const days = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
// ថ្ងៃនេះជាថ្ងៃពុធ (3)។ តើ 10 ថ្ងៃទៀតជាថ្ងៃអ្វី? 5 ថ្ងៃមុន?
console.log(days[mod(3 + 10, 7)]); // "Sat"
console.log(days[mod(3 - 5, 7)]); // "Fri"
មើលបន្ទាត់ទីពីរ៖ (3 - 5) % 7 នឹងជា -2 ហើយ days[-2] គឺ undefined។ Helper mod ជួយសង្គ្រោះអ្នកម្តងទៀត។
ឧបករណ៍ប្រតិទិន (ក្រឡា "តើខែនេះចាប់ផ្តើមថ្ងៃអ្វី?") ត្រូវបានសាងសង់ពីរឿងនេះយ៉ាងពិតប្រាកដ៖ លេខថ្ងៃក្នុងសប្តាហ៍បូកនឹងចំនួនថ្ងៃ យក mod 7។
7. Hash Bucket
ត្រឡប់ទៅជំពូកទី 5 យើងបាននិយាយថា Set ឆ្លើយ "តើ X នៅទីនេះទេ?" ស្ទើរតែភ្លាមៗ។ នេះគឺជាល្បិចនៅពីក្រោយវា ហើយវាគឺជានព្វន្ត modular។
ស្រមៃមើល bucket ទទេ 8 ដែលដាក់លេខពី 0 ដល់ 7។ ដើម្បីរក្សាទុកឈ្មោះមួយ អ្នកបំប្លែងវាទៅជាលេខដោយ hash function បន្ទាប់មកប្រើ % 8 ដើម្បីជ្រើស bucket។ ក្រោយមក ដើម្បីរកឈ្មោះនោះ អ្នកគណនាលេខដូចគ្នា ហើយបើកតែ bucket មួយនោះប៉ុណ្ណោះ ជំនួសឲ្យការស្វែងរកអ្វីៗទាំងអស់។
Hash function តូចមួយដែលបូកកូដតួអក្សរ៖
function hash(text) {
let h = 0;
for (const char of text) {
h = (h * 31 + char.codePointAt(0)) % 1000003;
}
return h;
}
for (const name of ["dara", "sokha", "vanna", "sreyneang"]) {
const h = hash(name);
console.log(name, h, h % 8);
}
// dara 75939 3
// sokha 617537 1
// vanna 974089 1
// sreyneang 70922 2
នៅទីនេះ h * 31 + code លាយអក្សរនីមួយៗចូលក្នុងលេខ ហើយ % 1000003 រក្សាវាកុំឲ្យធំពេក (បច្ចេកទេសដែលក៏ជៀសវាងដែនកំណត់ដែលអ្នកនឹងឃើញក្នុងជំពូកបន្ទាប់)។ បន្ទាប់មក h % 8 ជ្រើស bucket៖ dara ទៅ bucket 3, sokha និង vanna ទាំងពីរធ្លាក់ក្នុង bucket 1 ហើយ sreyneang ទៅ bucket 2។
ឈ្មោះពីរក្នុង bucket ដូចគ្នាហៅថា collision។ វាជារឿងធម្មតា ហើយគ្រប់ hash table ដោះស្រាយវា ឧទាហរណ៍ដោយរក្សាបញ្ជីខ្លីក្នុង bucket នីមួយៗ។ ការស្វែងរកបញ្ជីខ្លីនៅតែលឿនជាងការស្វែងរកអ្វីៗទាំងអស់ឆ្ងាយណាស់។ ជាមួយ bucket ច្រើនជាងធាតុ collision នៅតែកម្រ។ អ្នកនឹងរាប់ថាវាអាចកើតមានប៉ុនណាយ៉ាងពិតប្រាកដនៅក្នុង មូលដ្ឋានគ្រឹះប្រូបាប។
Hash function ពិតលាយបានល្អជាងប្រដាប់លេងនេះឆ្ងាយ ហើយភាសាពិតជ្រើសរើសព័ត៌មានលម្អិតឲ្យអ្នក។ អ្នកនឹងមិនសរសេរវាដោយដៃទេ ប៉ុន្តែការដឹង hash % size ពន្យល់ថាហេតុអ្វី Set លឿន និងហេតុអ្វី hash អាក្រក់ធ្វើឲ្យវាយឺត។
8. Check Digit និងក្បួនដោះស្រាយ Luhn
ខ្ទង់ចុងក្រោយនៃលេខកាតធនាគារមិនមែនចៃដន្យទេ។ វាគឺជា check digit ដែលគណនាពីខ្ទង់ផ្សេងទៀត ដើម្បីឲ្យកំហុសវាយស្ទើរតែតែងតែត្រូវបានរកឃើញ។ កាតឥណទាន និងកាតឥណពន្ធ លេខអត្តសញ្ញាណជាច្រើន និងលេខ IMEI ប្រើ ក្បួនដោះស្រាយ Luhn ដែលបង្កើតក្នុងឆ្នាំ 1954 ហើយនៅតែមានគ្រប់ទីកន្លែង។ វាចាប់បានគ្រប់ខ្ទង់តែមួយដែលវាយខុស និងភាគច្រើននៃខ្ទង់ជិតគ្នាដែលប្តូរកន្លែង ហើយវាត្រូវការតែ %។
រូបមន្តសម្រាប់ពិនិត្យលេខមួយ៖
- ចាប់ផ្តើមពីខ្ទង់ ខាងស្តាំបំផុត ផ្លាស់ទីទៅឆ្វេង។ ទុកខ្ទង់ទីមួយតាមដើម គុណពីរ ខ្ទង់ទីពីរ ទុកខ្ទង់ទីបី គុណពីរខ្ទង់ទីបួន ហើយបន្តទៀត។
- ប្រសិនបើខ្ទង់ដែលគុណពីរធំជាង 9 សូមដក 9 (វាដូចគ្នានឹងការបូកខ្ទង់ទាំងពីររបស់វា ដូច្នេះ
16ក្លាយជា1 + 6 = 7)។ - បូកអ្វីៗទាំងអស់។
- លេខត្រឹមត្រូវ ប្រសិនបើផលបូកជាពហុគុណនៃ 10 ដែលជា
total % 10 === 0។
សាកល្បងដើរតាមលេខតេស្តស្តង់ដារ 79927398713។ អានពីខាងស្តាំ៖
| ខ្ទង់ (ពីស្តាំទៅឆ្វេង) | 3 | 1 | 7 | 8 | 9 | 3 | 7 | 2 | 9 | 9 | 7 |
|---|---|---|---|---|---|---|---|---|---|---|---|
| គុណពីរ? | ទេ | បាទ/ចាស | ទេ | បាទ/ចាស | ទេ | បាទ/ចាស | ទេ | បាទ/ចាស | ទេ | បាទ/ចាស | ទេ |
| បន្ទាប់ពីជំហានទី 2 | 3 | 2 | 7 | 7 | 9 | 6 | 7 | 4 | 9 | 9 | 7 |
8 ដែលគុណពីរគឺ 16 ដក 9 ផ្តល់ 7។ 9 ដែលគុណពីរគឺ 18 ដក 9 ផ្តល់ 9។ ផលបូកគឺ 3 + 2 + 7 + 7 + 9 + 6 + 7 + 4 + 9 + 9 + 7 = 70 ហើយ 70 % 10 === 0 ដូច្នេះលេខនេះត្រឹមត្រូវ។
ក្នុងកូដ៖
function luhnCheck(digits) {
const clean = String(digits).replace(/\D/g, ""); // ដកដកឃ្លា និងសញ្ញាចុច
if (clean.length < 2) return false;
let sum = 0;
let double = false;
for (let i = clean.length - 1; i >= 0; i--) {
let d = Number(clean[i]);
if (double) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
double = !double; // ឆ្លាស់៖ ទេ បាទ/ចាស ទេ បាទ/ចាស...
}
return sum % 10 === 0;
}
console.log(luhnCheck("79927398713")); // true
console.log(luhnCheck("79927398714")); // false (វាយខ្ទង់ចុងក្រោយខុស)
/\D/g គឺជា pattern មានន័យថា "គ្រប់តួអក្សរដែលមិនមែនជាខ្ទង់" ដូច្នេះ "4539 1488 0343 6467" ក្លាយជាខ្ទង់ធម្មតា។ ការប្រើ double = !double គឺជា boolean toggle ពី Boolean Logic។
ដើម្បី បង្កើត លេខកាត អ្នកធ្វើបញ្ច្រាស៖ ជ្រើស check digit ដែលធ្វើឲ្យផលបូកជាពហុគុណនៃ 10។ ការសាកល្បងលទ្ធភាពទាំងដប់គឺសាមញ្ញ និងលឿនគ្រប់គ្រាន់៖
function luhnCheckDigit(partial) {
const clean = String(partial).replace(/\D/g, "");
for (let d = 0; d <= 9; d++) {
if (luhnCheck(clean + d)) return d;
}
}
console.log(luhnCheckDigit("7992739871")); // 3
ពាក្យប្រុងប្រយ័ត្នមួយ៖ Luhn រកឃើញកំហុសវាយ មិនមែនការបន្លំទេ។ អ្នកណាក៏អាចបង្កើតលេខដែលឆ្លងកាត់បាន។ វាជាការពិនិត្យដំបូងដែលថោកក្នុង form ដើម្បីឲ្យអ្នកអាចនិយាយថា "នោះមើលទៅមិនត្រឹមត្រូវ" មុនពេលអ្នកទាក់ទងសេវាបង់ប្រាក់ដូចជា KHQR ឬ card processor។ កុំចាត់ទុកវាជាភស្តុតាងថាកាតពិតនោះឡើយ។
9. រូបមន្ត៖ modular.js សម្រាប់ mathlab
បង្កើត src/modular.js ក្នុង mathlab ហើយប្រមូលអ្វីៗទាំងអស់ពីជំពូកនេះ៖
// Modulo ពិត៖ លទ្ធផលតែងតែស្ថិតនៅចន្លោះ 0 និង m - 1។
export function mod(n, m) {
return ((n % m) + m) % m;
}
// វិលជុំ n ចូលក្នុងដែន min..max (រួមទាំងពីរ)។
export function wrap(n, min, max) {
return min + mod(n - min, max - min + 1);
}
// Carousel helper៖ index វិលជុំ។
export function nextIndex(i, length) {
return mod(i + 1, length);
}
export function prevIndex(i, length) {
return mod(i - 1, length);
}
// ការពិនិត្យ Luhn៖ តើលេខបែបកាតនេះត្រឹមត្រូវទេ?
export function luhnCheck(digits) {
const clean = String(digits).replace(/\D/g, "");
if (clean.length < 2) return false;
let sum = 0;
let double = false;
for (let i = clean.length - 1; i >= 0; i--) {
let d = Number(clean[i]);
if (double) {
d *= 2;
if (d > 9) d -= 9;
}
sum += d;
double = !double;
}
return sum % 10 === 0;
}
// ខ្ទង់ចុងក្រោយណាធ្វើឲ្យលេខត្រឹមត្រូវ?
export function luhnCheckDigit(partial) {
const clean = String(partial).replace(/\D/g, "");
for (let d = 0; d <= 9; d++) {
if (luhnCheck(clean + d)) return d;
}
}
បន្ថែម export ទៅ src/index.js៖
export * from "./modular.js";
បន្ទាប់មកធ្វើបច្ចុប្បន្នភាព demo.js៖
import {
mod,
wrap,
nextIndex,
prevIndex,
luhnCheck,
luhnCheckDigit,
} from "./src/modular.js";
console.log(-1 % 5, mod(-1, 5));
console.log(mod(7, 5), mod(-7, 5), mod(10, 5));
console.log(wrap(13, 1, 12), wrap(0, 1, 12));
console.log(nextIndex(4, 5), prevIndex(0, 5));
console.log(luhnCheck("79927398713"), luhnCheck("79927398714"));
console.log(luhnCheckDigit("7992739871"));
console.log(luhnCheck("4539 1488 0343 6467"));
console.log(luhnCheck("4539 1488 0343 6476"));
ដំណើរការវា៖
node demo.js
-1 4
2 3 0
1 12
0 4
true false
3
true
false
បន្ទាត់ទីមួយបង្ហាញអន្ទាក់ និងដំណោះស្រាយនៅក្បែរគ្នា។ ពីរបន្ទាត់ចុងក្រោយបង្ហាញ Luhn ចាប់បានកំហុសវាយ៖ ការប្តូរខ្ទង់ពីរចុងក្រោយនៃលេខកាតត្រឹមត្រូវ 6467 ទៅជា 6476 ធ្វើឲ្យវាបរាជ័យ។
10. សាកល្បងដោយខ្លួនឯង
- Remainder ឬ modulo? ទាយ បន្ទាប់មកពិនិត្យ៖
-10 % 3,mod(-10, 3),10 % -3។ មួយណាក្នុងចំណោមទាំងនេះដែលមិនរំពឹងទុក? - ទំព័រ និង slot។ តារាងមួយបង្ហាញ 25 ជួរក្នុងមួយទំព័រ។ សរសេរ
locate(n)ដែលត្រឡប់{ page, row }សម្រាប់ធាតុលេខn(រាប់ពី 0)។ តើធាតុ100ផ្តល់អ្វី? - សាងសង់នាឡិកា។ សរសេរ
addMinutes(time, delta)ដែលtimeជានាទីចាប់តាំងពីពាក់កណ្តាលអធ្រាត្រ (0ដល់1439) ហើយdeltaអាចអវិជ្ជមាន។ ធ្វើទ្រង់ទ្រាយលទ្ធផលជា"HH:MM"។ តើ 00:10 ដក 30 នាទីស្មើប៉ុន្មាន? - ថ្ងៃសុក្របន្ទាប់។ ដោយប្រើ
daysនិងmodសរសេរdaysUntil(today, target)ដែលត្រឡប់ចំនួនថ្ងៃពីtodayរហូតដល់ថ្ងៃtargetបន្ទាប់ (ទាំងពីរជាលេខ0ដល់6)។ ចម្លើយសម្រាប់ today = ថ្ងៃសុក្រ និង target = ថ្ងៃសុក្រ គួរតែជា0។ - បំបែក Luhn។ យកលេខត្រឹមត្រូវមួយ ហើយប្តូរមួយខ្ទង់។ តើ
luhnCheckតែងតែបរាជ័យឬទេ? ឥឡូវប្តូរកន្លែងខ្ទង់ជិតគ្នាពីរ ហើយសាកល្បងម្តងទៀត។ រកឧទាហរណ៍មួយនៃការប្តូរកន្លែងដែល Luhn មិនចាប់បាន (ជំនួយ៖ ប្តូរខ្ទង់ជិតគ្នា09ទៅ90ក្នុង123409567)។ - ការចែកចាយ bucket។ Hash ពាក្យខុសៗគ្នា 20 ដោយ function
hashហើយរាប់ថាប៉ុន្មានធ្លាក់ក្នុង bucket នីមួយៗក្នុងចំណោម 8។ តើវាចែកចាយស្មើគ្នាទេ? សាកល្បង 16 bucket ហើយប្រៀបធៀប។
នព្វន្ត modular ដំណើរការ ព្រោះលេខក្នុងកុំព្យូទ័រមានទំហំថេរ ហើយវិលជុំ ដូចជានាឡិកាដែរ។ នៅក្នុងជំពូកបន្ទាប់ Integer, Overflow និងភាពជាក់លាក់ យើងនឹងមើលអ្វីដែលកើតឡើងនៅពេលលេខអស់កន្លែង និងហេតុអ្វីបានជាប្រាក់មិនគួររក្សាទុកជាលេខ floating-point ឡើយ។
ទិញកាហ្វេជូនខ្ញុំ
ចូលចិត្តមេរៀននេះមែនទេ? សូមពិចារណាទិញកាហ្វេជូនខ្ញុំមួយកែវ ដើម្បីគាំទ្រការបង្កើតមាតិកាឥតគិតថ្លៃបន្ថែមទៀត!