Яка поведінка цілого поділу?


209

Наприклад,

int result;

result = 125/100;

або

result = 43/100;

Чи буде результат завжди підлогою підрозділу? Що таке визначена поведінка?


5
Короткий зміст: підписане ціле ділення скорочується до нуля . Для негативних результатів це те саме, що і підлога (кругла до-нескінченності). (Остерігайтеся, що C89 цього не гарантує. Дивіться відповіді.)
Пітер Кордес

5
Всі продовжують говорити "усікати до нуля" або "стелі" або "підлоги", як код приймає обдумане рішення, яку техніку використовувати. Якби код міг говорити, він би сказав"I just throw the dam fraction part in the trash and move on with life"
Тимофі Л.Ж. Стюарт

3
@ TimothyL.J.Stewart "Код" приймає обдумане рішення. Відповідно до специфікації, ціле ділення мається на увазі на T (runcation)-поділ. Через це оператор модуль / залишок реалізується інакше, ніж якби він був іншою мовою, скажімо, Python або Ruby. Дивіться це для переліку різних способів роботи мов оператором модуля, і цей документ, у якому перераховано щонайменше п’ять загальних способів, якими мови програмування вирішують робити div / modulo.
13steinj

1
@ 13steinj Я розмовно розмовляю за коментарями, це перетворювалося на "усікання до нуля ... ні, це підлога ... ні, якщо негативна його стеля ...", іноді технічні характеристики не поширюються в майбутнє разом із людською пам'яттю як ми хочемо, але інтуїтивно знаючи, що "частина фракції відкидається", ви можете отримати технічні моменти. Техніки - це важкий тягар, але інтуїція легка і освіжаюча, як вітер, я буду носити їх далеко і впоперек, і коли потрібно, я буду знати, з чого почати. Як той папір, який ви зв'язали, дякую.
Тімоті Л. Дж. Стюарт

Я відповів тут, наголосивши на евклідовому поділі (взаємодію між цілим поділом та оператором модуля).
Піко Вінсент

Відповіді:


182

Чи буде результат завжди підлогою підрозділу? Що таке визначена поведінка?

Так, цілий коефіцієнт двох операндів.

6.5.5 Мультиплікаційні оператори

6 Коли цілі числа поділяються, результатом / оператора є алгебраїчний коефіцієнт, який відкидається дробовою частиною. 88) Якщо коефіцієнт a / b є представним, вираз (a / b) * b + a% b дорівнює a.

та відповідна виноска:

88) Це часто називають "усіченням до нуля".

Звичайно, слід зазначити два моменти:

3 Звичайні арифметичні перетворення виконуються на операндах.

і:

5 Результатом / оператора є коефіцієнт від ділення першого операнда на другий; результат оператора% - залишок. В обох операціях, якщо значення другого операнда дорівнює нулю, поведінка не визначена.

[Примітка: наголос мій]


26
... якщо, звичайно, ви не розділите від'ємне число на додатне (або vv), в цьому випадку це буде стеля.
Буде

74
Це ні підлога, ні стеля, це укорочення дробової частини, це концептуально інше!
lornova

38
@Will A: Ні. Вона визначається як усічення до нуля. Якщо називати це чим-небудь іншим, це просто додасть плутанини, тому, будь ласка, утримайтеся від цього.
Мартін Йорк

44
Принаймні з математичної точки зору, відсікання до нуля еквівалентно "якщо> 0, тоді стеля в інших поверхах". Я думаю, що просто називати це обрізанням простіше, ніж називати підлогу / стелю, але будь-яке дійсне. Незважаючи на те, пункт Вілла А справедливий: відповідь Деркґенґійса частково неправильна, оскільки він заявив, що ОП має рацію в тому, що результат є підлогою підрозділу.
Брайан

9
@Philip Potter: Я не думаю, що це було визначено в C89, і це не в стандарті C ++ 1998 року. У тих, звичайно , повинні (a / b) * b + a % b == aбули бути задоволені, і абсолютне значення має a % bбуло бути менше a, але буде чи a % bбув негативним для негативного aабо bне було зазначено.
Девід Торнлі

39

Dirkgently дає чудовий опис цілого поділу в C99, але ви також повинні знати, що в C89 ціле ділення з від'ємним операндом має напрямок, визначений реалізацією.

З проекту ANSI C (3.3.5):

Якщо будь-який операнд від'ємний, чи є результат / оператора найбільшим цілим числом, меншим від алгебраїчного коефіцієнта, або найменшим цілим числом, більшим за алгебраїчний коефіцієнт, визначено реалізацією, як і знак результату оператора%. Якщо показник a / b є репрезентативним, вираз (a / b) * b + a% b дорівнює a.

Тому будьте уважні з негативними цифрами, коли ви застрягли у компіляторі C89.

Приємно, що C99 обрав усечення до нуля, оскільки саме так це зробив FORTRAN. Дивіться це повідомлення на comp.std.c.


2
А пункт 5 передмови в проекті N9956 C99 згадується reliable integer divisionяк нова мовна особливість. Дивовижно *-*.
Ciro Santilli 郝海东 冠状 病 六四 事件 法轮功

Урізання - це те, як поводиться найпоширеніше обладнання процесора (наприклад, x86), тому було б шалено зробити інший вибір. IDK, який вийшов першим, семантика Fortran або апаратне поведінка, але не випадково вони теж однакові.
Пітер Кордес

2
@PeterCordes: Найчастіше апаратне забезпечення процесора могло б здійснити розподіл на більшість констант швидше, ніж вони могли зробити поділ обрізки. ІМХО, було б краще для Стандарту , щоб сказати , що expr1 / expr2і expr1 % expr2повинні бути узгоджені між собою , коли обидва примірники expr1об'єднують одні й ті ж об'єкти , таким же чином, також і для expr2, але вибір усічення проти поділу поверхового інакше Невідомо. Це дозволило б більш ефективно генерувати код, не порушуючи особливої ​​сумісності (а реалізація може задокументувати конкретну поведінку, якщо схильна)
supercat

23

Якщо результат негативний, C скорочується до 0, а не до підлоги - я дізнався, читаючи про те, чому ціле ділення Python завжди поверхи тут: Чому підлоги підрозділу Python


3
Я погоджуюсь з коментарем, цікаво, чи корисне використання негативу (нега% пози)? У відповідній записці мені цікаво, чи потрібна арифметично-некоректна поведінка в деяких випадках "непідписаного> підписаного"? Я можу зрозуміти обґрунтування того, що не потрібно завжди правильної поведінки; Я не бачу підстав вимагати неправильної поведінки.
supercat

8
+1 - відмінна довідка щодо того, чому настил - це правильна поведінка для цілого поділу (всупереч визначенню C, яке порушено і майже ніколи не корисно).
R .. GitHub СТОП ДОПОМОГА ВІД

@supercat Поміркуйте:, filtered = (k - 1) * filtered + value + carry; carry = filtered % factor; filtered /= factorповторене зі зміною значень value. Це робить приємне ціле наближення до фільтра низьких частот першого порядку з постійною часом k..., але воно є симетричним лише тоді, коли поділ обрізається і carryотримує негативні значення. Обидва способи поведінки для поділу час від часу корисні.
панно

1
@hobbs: Я не думаю, що вищезгаданий код поводитиметься чисто, коли сигнали перетинають нуль. Якщо divоператор з розділеним флорацією і factorнепарний, то filtered += (filter+(factor div 2)) div factorвін дасть чисту та симетричну поведінку для всіх значень до INT_MAX-(factor div 2).
supercat

@supercat все-таки працює; цей код лише трохи відганяється від того, що я деякий час працював у контролері атомного годинника.
варення

21

Так, результат завжди скорочується до нуля. Він буде округлювати до найменшого абсолютного значення.

-5 / 2 = -2
 5 / 2 =  2

Для знаків без підпису та негативу це те саме, що і підлогу (округлення до -інфінітію).


43
Обрізання, а не підлога.
dan04

9
@ dan04: yep floor буде дійсним лише для натуральних чисел :)
Леонід

13

Чи буде результат завжди підлогою підрозділу?

Ні. Результат змінюється, але коливання відбувається лише для негативних значень.

Що таке визначена поведінка?

Щоб було зрозуміло, круглі підлоги у бік негативної нескінченності, тоді як ціле ділення округляє до нуля (скорочення)

Для позитивних значень вони однакові

int integerDivisionResultPositive= 125/100;//= 1
double flooringResultPositive= floor(125.0/100.0);//=1.0

Для від’ємного значення це різне

int integerDivisionResultNegative= -125/100;//=-1
double flooringResultNegative= floor(-125.0/100.0);//=-2.0

0

Я знаю, що люди відповіли на ваше запитання, але просто кажучи:

5 / 2 = 2 // оскільки і 5, і 2 є цілими числами, а розділення на цілі числа завжди скорочує десяткові знаки

5.0 / 2 or 5 / 2.0 or 5.0 /2.0 = 2.5 // тут або 5, або 2, або обидва мають десятковий, отже, коефіцієнт, який ви отримаєте, буде десятковим.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.