Работа с процентами с использованием целочисленного деления в сборке x86 - PullRequest
0 голосов

Я работаю в Assembly (x86) и работаю с процентами. Моя проблема заключается в следующем:

У меня есть какое-то значение total_sum, которое представляет 100%.

Я рассчитываю total_sum/100, чтобы получить значение, которое представляет 1%:

xorl %edx, %edx
movl total_sum, %eax
movl $100, %ecx
divl %ecx

Позже в моей программе я использую результат этого деления для вычисления процента, представленного некоторым другим значением.

Пример расчета, выполненного с помощью калькулятора (с плавающей запятой):

515 представляет 100%, какой процент представляет 506?

515/100 = 5,15
506 / 5,15 = 98,25

Это означает: 506 составляет около 98% от 515.

К сожалению, при использовании ассемблера и целочисленной арифметики вычисление выглядит так:

515/100 = 5
506/5 = 101

Это означает, что 506 представляет 101% от 515.

Однако я не хочу, чтобы результаты> 100%.

Я пытался использовать значение в %edx из первого деления, чтобы внести некоторые исправления. Однако округление %eax (с приращением, если %edx указывает, что первая цифра после десятичной точки 5 или более) не сильно помогло.

Как я могу убедиться, что я не получаю значения больше 100%?

1 Ответ

2 голосов
/ 21 мая 2019

Я полностью отредактировал ваш вопрос, потому что это было нелегко понять. Я надеюсь, что я полностью понял ваш вопрос, и вопрос все еще спрашивает, что вы хотите задать.

Проблема, которую вы описываете, на самом деле не является проблемой языка ассемблера, но это проблема, связанная с любым языком программирования, который может выполнять целочисленную арифметику, например C / C ++, Java, Pascal и многими другими.

Поэтому я удалил тег x86 из вашего вопроса и добавил тег integer-division.

Следующая попытка:

Я пытался использовать значение в %edx из первого деления, чтобы внести некоторые исправления. Однако округление %eax ... не очень помогло.

Не поможет вам. Давайте посмотрим на второй расчет, который вы выполните позже:

570/5 = 114
570/6 = 95
510/5 = 102
510/6 = 85

Таким образом, если (исправленный) результат первого деления равен 5, значение 510 будет вычислено как 102%, хотя 510 <515. </p>

И если (исправленный) результат первого деления равен 6, значение 570 будет вычислено как 95%, хотя 570> 515.

Это означает, что нет целого числа one_percent, представляющего 1%, и которое даст вам правильные результаты при выполнении операции percentage = number / one_percent.

Единственный шанс, который у вас есть, - выполнить следующий расчет в конце вашей программы :

percentage = (100 * number) / total_sum

Обратите внимание, что порядок операций имеет значение почти всегда, когда используется целочисленная арифметика. Таким образом, следующий расчет не дает те же результаты, что и расчет выше:

percentage = 100 * (number / total_sum)

Используя язык ассемблера, вы можете выполнить первый расчет следующим образом:

mov $100, %edx
mov some_number, %eax
mull %edx
  ; Now (edx:eax) contains the 64-bit value (100*some_number)
mov total_sum, %ecx
divl %ecx
  ; Now eax contains the 32-bit value (100*some_number)/total_sum
...