Помилка на одиницю (off-by-one error) — це логічна помилка, яка містить число, яке відрізняється від запланованого значення на +1 або −1. Це часто відбувається при програмуванні, коли ітерація циклу повторюється на один раз більше або на один раз менше ніж потрібно.
Основні причини це:
- неправильне розуміння нестрогої нерівності (≤) як умови виходу з циклу в той час як потрібна сувора нерівність (<), або навпаки.
- плутанина, пов'язана з використанням нумерації від нуля
Приклади
Помилка парканного (або телеграфного) стовпа
Помилка парканного стовпа (іноді її називають помилкою телеграфного стовпа, ліхтарного стовпа або паркану ) — це особливий тип помилки «на одиницю». Ця помилка описана дуже давно, наприклад з'являється в роботах Вітрувія.
Задачі, які можна сформулювати як :
Пряма задача Вам потрібно побудувати паркан 10 метрів завдовжки. Через кожен метр повинен стояти стовп. Скільки стовпів вам необхідно? | Обернена задача Якщо у вас є 10 стовпів, які потрібно встановити в паркані кожен метр, то яка буде довжина паркану? | |||
Звісно відповідь залежить від конструкції паркану, і в нашому випадку, якщо ми вказуємо що паркан починається з стовпа, потім йде секція паркану, далі стовп, і так далі, та в кінці паркан закінчується стовпом.
Швидка інтуїтивна відповідь що для прямої задачі потрібно 10 стовпів, а для оберненої - довжина 10 метрів. Але такі відповіді є неправильними, оскільки довжина паркана дорівнює кількості секцій, а кількість секцій на одну менше ніж стовпів. Якщо паркан має 10 секцій то він має довжину 10 метрів, але має 11 стовпів. Та обернений варіант 10 стовпів це 9 секцій тобто 9 метрів.
Помилки в подібних задачах виникають через підрахунок предметів, а не проміжків між ними, або навпаки, або нехтування питанням про те, чи слід рахувати один чи обидва кінці ряду.
Приклад цієї помилки може виникнути в мовах розрахунків MATLAB, а також numpy в функціях linspace()
та arange()
.
Функція linspace
має параметри linspace(lower_value, upper_value, number_of_values )
Програміст, який неправильно зрозуміє третій параметр, та захоче отримати масив який починається з 0, закінчується 10, проміжками по 2 одиниці - [0, 2, 4, 6, 8, 10]
, подумає що третій параметр повинен бути (10-0)/2 = 5
.
Але linspace(0, 10, 5)
повертає масив з 5 значеннями, розраховуючи однакові проміжки [0, 2.5, 5, 7.5, 10]
.
А інша функція numpy
, arange(0, 10, 2)
поверне значення [0, 2, 4, 6, 8]
що не включає останнє значення 10.
Така помилка може виникати не лише при вимірюванні довжини чи програмуванні. Наприклад, піраміда часу, що повинна складатись з 120 блоків, та заплановано що кожні 10 років будується новий блок. Автор конструкції хотів продемонструвати що таке 1200 років, але піраміда буде побудована за 1190 років. Одна з найдавніших помилок на одиницю також пов'язана з часом, коли на початку впровадження юліанського календаря протягом 36 років обчислювали високосні роки неправильно, оскільки священики вирішили що високосний рік повинен бути кожні три року, а не через кожні три року.
Ітерація по масиву
Розглянемо масив елементів, з елементами від m до n (включно) які потрібно обробити. Скільки там об'єктів? Інтуїтивно зрозумілою відповіддю може бути n − m, але вона відрізняється на одиницю, демонструючи помилку парканного стовпа тому що правильна відповідь n − m + 1. Саме тому діапазони в програмуванні часто представлені як напіввідкритими діапазонами. Діапазон [m, n] (включно) представляється [m, n + 1) (від m включно до n виключно), щоб уникнути таких помилок.
Наприклад, цикл, який повторюється п’ять разів (від 0 до 4 включно), можна записати як напіввідкритий інтервал від 0 до 5:
for (index = 0; index < 5; index++) { /* тіло цикла */ }
Перша ітерація циклу виконується в перший раз з index = 0, потім index = 1, index = 2, index = 3 і, нарешті index = 4.
В той момент коли index зростає до 5, умова index < 5 стає хибною, і цикл завершується. Однак, сама процедура перевірки умови, порівняння <= (менше або дорівнює) виконується шість разів. Якщо перевірка буде викликати якусь функцію або дію, то ця дія буде виконана шість разів.
Схожим образом може виникнути така помилка може виникнути, якщо замість циклу while-do
використовувати цикл do-while (або навпаки).
Див. також
Примітки
- Moniot, Robert K., , Fordham University, архів оригіналу за 5 березня 2016, процитовано 7 липня 2016.
Вікіпедія, Українська, Україна, книга, книги, бібліотека, стаття, читати, завантажити, безкоштовно, безкоштовно завантажити, mp3, відео, mp4, 3gp, jpg, jpeg, gif, png, малюнок, музика, пісня, фільм, книга, гра, ігри, мобільний, телефон, android, ios, apple, мобільний телефон, samsung, iphone, xiomi, xiaomi, redmi, honor, oppo, nokia, sonya, mi, ПК, web, Інтернет
Pomilka na odinicyu off by one error ce logichna pomilka yaka mistit chislo yake vidriznyayetsya vid zaplanovanogo znachennya na 1 abo 1 Ce chasto vidbuvayetsya pri programuvanni koli iteraciya ciklu povtoryuyetsya na odin raz bilshe abo na odin raz menshe nizh potribno Osnovni prichini ce nepravilne rozuminnya nestrogoyi nerivnosti yak umovi vihodu z ciklu v toj chas yak potribna suvora nerivnist lt abo navpaki plutanina pov yazana z vikoristannyam numeraciyi vid nulyaPrikladiPomilka parkannogo abo telegrafnogo stovpa Pomilka parkannogo stovpa inodi yiyi nazivayut pomilkoyu telegrafnogo stovpa lihtarnogo stovpa abo parkanu ce osoblivij tip pomilki na odinicyu Cya pomilka opisana duzhe davno napriklad z yavlyayetsya v robotah Vitruviya Zadachi yaki mozhna sformulyuvati yak Dlya pryamogo parkanu z 10 sekcij potribno 11 stovpiv Zagalom dlya n rozdiliv znadobitsya n 1 stovp Pryama zadacha Vam potribno pobuduvati parkan 10 metriv zavdovzhki Cherez kozhen metr povinen stoyati stovp Skilki stovpiv vam neobhidno Obernena zadacha Yaksho u vas ye 10 stovpiv yaki potribno vstanoviti v parkani kozhen metr to yaka bude dovzhina parkanu Zvisno vidpovid zalezhit vid konstrukciyi parkanu i v nashomu vipadku yaksho mi vkazuyemo sho parkan pochinayetsya z stovpa potim jde sekciya parkanu dali stovp i tak dali ta v kinci parkan zakinchuyetsya stovpom Shvidka intuyitivna vidpovid sho dlya pryamoyi zadachi potribno 10 stovpiv a dlya obernenoyi dovzhina 10 metriv Ale taki vidpovidi ye nepravilnimi oskilki dovzhina parkana dorivnyuye kilkosti sekcij a kilkist sekcij na odnu menshe nizh stovpiv Yaksho parkan maye 10 sekcij to vin maye dovzhinu 10 metriv ale maye 11 stovpiv Ta obernenij variant 10 stovpiv ce 9 sekcij tobto 9 metriv Pomilki v podibnih zadachah vinikayut cherez pidrahunok predmetiv a ne promizhkiv mizh nimi abo navpaki abo nehtuvannya pitannyam pro te chi slid rahuvati odin chi obidva kinci ryadu Priklad ciyeyi pomilki mozhe viniknuti v movah rozrahunkiv MATLAB a takozh numpy v funkciyah linspace ta arange Funkciya linspace maye parametri linspace i lower value i i upper value i i number of values i Programist yakij nepravilno zrozumiye tretij parametr ta zahoche otrimati masiv yakij pochinayetsya z 0 zakinchuyetsya 10 promizhkami po 2 odinici 0 2 4 6 8 10 podumaye sho tretij parametr povinen buti 10 0 2 5 Ale linspace 0 10 5 povertaye masiv z 5 znachennyami rozrahovuyuchi odnakovi promizhki 0 2 5 5 7 5 10 A insha funkciya numpy arange 0 10 2 poverne znachennya 0 2 4 6 8 sho ne vklyuchaye ostannye znachennya 10 Taka pomilka mozhe vinikati ne lishe pri vimiryuvanni dovzhini chi programuvanni Napriklad piramida chasu sho povinna skladatis z 120 blokiv ta zaplanovano sho kozhni 10 rokiv buduyetsya novij blok Avtor konstrukciyi hotiv prodemonstruvati sho take 1200 rokiv ale piramida bude pobudovana za 1190 rokiv Odna z najdavnishih pomilok na odinicyu takozh pov yazana z chasom koli na pochatku vprovadzhennya yulianskogo kalendarya protyagom 36 rokiv obchislyuvali visokosni roki nepravilno oskilki svyasheniki virishili sho visokosnij rik povinen buti kozhni tri roku a ne cherez kozhni tri roku Iteraciya po masivu Rozglyanemo masiv elementiv z elementami vid m do n vklyuchno yaki potribno obrobiti Skilki tam ob yektiv Intuyitivno zrozumiloyu vidpoviddyu mozhe buti n m ale vona vidriznyayetsya na odinicyu demonstruyuchi pomilku parkannogo stovpa tomu sho pravilna vidpovid n m 1 Same tomu diapazoni v programuvanni chasto predstavleni yak napivvidkritimi diapazonami Diapazon m n vklyuchno predstavlyayetsya m n 1 vid m vklyuchno do n viklyuchno shob uniknuti takih pomilok Napriklad cikl yakij povtoryuyetsya p yat raziv vid 0 do 4 vklyuchno mozhna zapisati yak napivvidkritij interval vid 0 do 5 for index 0 index lt 5 index tilo cikla Persha iteraciya ciklu vikonuyetsya v pershij raz z index 0 potim index 1 index 2 index 3 i nareshti index 4 V toj moment koli index zrostaye do 5 umova index lt 5 staye hibnoyu i cikl zavershuyetsya Odnak sama procedura perevirki umovi porivnyannya lt menshe abo dorivnyuye vikonuyetsya shist raziv Yaksho perevirka bude viklikati yakus funkciyu abo diyu to cya diya bude vikonana shist raziv Shozhim obrazom mozhe viniknuti taka pomilka mozhe viniknuti yaksho zamist ciklu while do vikoristovuvati cikl do while abo navpaki Div takozhPrincip Dirihle Pohibka okruglennya Numeraciya vid nulyaPrimitkiMoniot Robert K Fordham University arhiv originalu za 5 bereznya 2016 procitovano 7 lipnya 2016