Разделение, остатки и допустимые только действительные числа - PullRequest
2 голосов
/ 03 апреля 2010

Попытка выяснить этот псевдокод. Предполагается следующее .... Я могу использовать только целые числа без знака и со знаком (или long). Отдел возвращает реальное число без остатка. Мод возвращает реальное число. Фракции и десятичные дроби не обрабатываются.

INT I = 41828;
INT C = 15;
INT D = 0;

D = (I / 65535) * C;

Как бы вы обработали дробь (или десятичное значение) в этой ситуации? Есть ли способ использовать отрицательное значение для представления остатка?

В этом примере I / 65535 должно быть 0,638, однако с учетом ограничений я получаю 0 с MOD 638. Как я могу затем умножить на C, чтобы получить правильный ответ?

Надеюсь, что это имеет смысл.

MOD здесь на самом деле возвращает 23707, а не 638. (Надеюсь, я прав в этом :))

Ответы [ 3 ]

3 голосов
/ 03 апреля 2010

Если бы вы изменили порядок операций в последней строке, вы получили бы целочисленный ответ, который вы ищете (9, если мои вычисления верны)

D = (I * C) / 65535
/* D == 9 */

Это ответ, который вы ищете?

0 голосов
/ 06 апреля 2010

Что ж, одним из способов обработки десятичных дробей является эта функция деления замены. У этой техники есть множество явных недостатков.

ALT DIV (dividend, divisor) returns (decimal, point)
for point = 0 to 99
  if dividend mod divisor = 0 return dividend / divisor, point
  dividend = divident * 10
return dividend / divisor, 100
0 голосов
/ 06 апреля 2010

Предполагая, что это значения, которые вы всегда используете для этого вычисления, я бы сделал что-то вроде:

 D = I / (65535 / C);

или

 D = I / 4369;

Поскольку C имеет значение 65535. Это поможет уменьшить вероятность превышения доступного диапазона целых чисел (т. Е. Если у вас есть только 16-битные целые числа без знака).

В более общем случае вы, если думаете, что существует риск того, что умножение I и C приведет к значению за пределами допустимого диапазона целочисленного типа, который вы используете (даже если конечный результат будет внутри этого диапазон) вы можете вычленить GCD числителя и знаменателя, как в:

INT I = 41828; 
INT C = 15; 
INT DEN = 65535;

INT GCDI = GCD(I, DEN);
DEN = DEN / GCDI;
I = I / GCDI;

INT GCDC = GCD(C, DEN);
DEN = DEN / GCDC;
C = C / GCDC;

INT D = (I * C) / DEN;

Где DEN - ваш знаменатель (в данном случае 65535). Это не даст вам правильного ответа во всех случаях, особенно если I и C оба взаимно просты с DEN и I * C> MAX_INT.

Что касается более крупного вопроса, который вы поднимаете, деление целочисленных значений всегда теряет десятичный компонент (эквивалентный функции floor). Единственный способ сохранить информацию, содержащуюся в том, что мы считаем «десятичной» частью, - это остаток, который можно вывести из модуля. Я настоятельно рекомендую вам не смешивать значения этих различных систем счисления. Целые числа - это просто целые числа. Если вам нужно, чтобы они были числами с плавающей точкой, вы должны использовать числа с плавающей точкой, а не целые числа. Если все, что вас интересует, это отображение десятичной части для пользователя (то есть вы на самом деле не используете ее для дальнейших вычислений), тогда вы могли бы написать подпрограмму для преобразования остатка в строку символов, представляющую остаток.

...