2013-04-22 3 views
21

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

Вопрос:

Как я могу умножить любой вход (Float, Int и т.д.) на 7, without using the* оператор в TWO steps.

Если кто-нибудь может дать мне ответ на этот вопрос с объяснением, это было бы очень полезно.

с двумя ступенями, я имею в виду предположим, что вы работаете цикл (я = 0; я < 7; я ++) в тот случай, число шагов будет> 2, а также тип конверсии, DIVISION, Сложение и т.д. (Подсчет шагов).

+4

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

+18

вы можете использовать оператор '/' –

+3

Что считается шагом? Кроме того, какая правильность ожидается? –

ответ

34

Предполагая float x или double x определяется в объеме. Тогда я вижу следующие возможности умножить его на 7 без использования * оператора:

В C++, вы можете использовать стандартные функторы (первый шаг: создать функтор, второй шаг: вызов функтора):

x = std::multiplies<float>()(x, 7.0f); // if x is a float 
x = std::multiplies<double>()(x, 7.0); // if x is a double 

Или только использование деление (Так как компилятор уже оценивает 1.0/7.0, это только один шаг):

x = x/(1.0f/7.0f); // if x is a float 
x = x/(1.0/7.0); // if x is a double 

Или используйте оператор *= (технически, это не * ОПА rator, но это только один единственный шаг):

x *= 7.0f; // if x is a float 
x *= 7.0; // if x is a double 

Или использовать сложение в логарифмическом масштабе (это не следует воспринимать очень серьезно, а так как это требует более двух «шагов»):

x = exp(log(x) + log(7.0)); 

Другой вариант - использовать инструкцию по сборке, но я не хочу писать это сейчас, так как это слишком сложно.

Если x целое, немного смещение есть еще один вариант, но не рекомендуется:

x = (x << 3) - x; // (x * 8) - x 
+5

Мне нравится решение логарифма. Я бы выбрал именно этот. См., Где можно применить одно логарифмическое тождество. – chris

+0

Я верю, что 'x = x/(1.0/7.0)' (или '(1.0f/7.0f))' скорее всего, будет оптимизирован в операции умножения в большинстве компиляторов, поэтому не должно быть проблем с производительностью. Хотя вам нужно ** позаботиться о целочисленном делении **, если тип 'int', просто остерегайтесь ** не ** писать' (1/7) '. –

+0

Если тип 'x' является' int', я предполагаю, что он будет вычисляться как 'double' (поскольку' 1.0/7.0') является двойным, а затем преобразован обратно в 'int', поэтому, я думаю, это будет равный 'x * 7', хотя и не уверен. – leemes

17

Вы могли бы просто использовать деление на седьмой:

x/(1.0/7) 

ли это засчитывается как «два шага» полностью зависит от вашего определения.

+3

Это будет делить на ноль. – leemes

+3

Erm, no. Разделение на 0 не помогает. –

+1

Я имел в виду это как математику, а не C++. Но конечно. –

0

Определение "два шага" ...

float result = 0.0f; 
float input = 3.14f; 
int times = 7; 

// steps 

while (times--) 
    result += input; 

Редактировать: деление на (1/7) не будет работать с int типа. Кроме того, в некоторых языках для того, чтобы работать с типом поплавка, вы должны пометить их как поплавки:

result = input/(1.0f/7.0f); 
+1

, но разве это не становится «входной мощностью 7?» –

+0

Вы совершенно правы, исправлены. :) Благодаря. –

+1

результат должен быть инициализирован 0, а не 1. – fgrieu

7

добавить его

//initialise s as the number to be multiplied 
sum=0 
for(i=0;i<7;i++) 
    sum+=s 
+6

в цикле будет рассчитано на 7 шагов. –

+0

Что вы подразумеваете под шагами? –

+0

@AswinMurugesh, Посмотрите комментарии OP. – chris

1

Вы также можете выполнить следующие действия для целых чисел:

(x<< 3) - x 
+2

не работает для float –

+0

@ HazemEl-Raffiee да, бит сдвиг не работает для float или double, обновляется, спасибо! – taocp

0
// String num = "10"; 
// int num = 10; 
float num = 10; 

BigDecimal bigD = new BigDecimal(num); 
BigDecimal seven = new BigDecimal(7); 
System.out.println(seven.multiply(bigD)); 

Вы могли бы используйте BigDecimal & его метод multiply. Работает практически во всем.

-3

Добавить 7 по x раз.

for(int i=0; i<10; i++) 
    result = result+7; 
+2

ОП запросил способ умножить на 7, чтобы не добавлять 70. –

+0

имеет смысл :). – Whoami

4

В C, следующий хак должен работать на поплавках, хранящихся в IEEE single precision floating point format:

#include <stdint.h> 

float mul7 (float x) { 
    union { 
     float f; 
     uint32_t i; 
    } u; 
    u.f = x; 
    u.i += (3 << 23); /* increment exponent by 3 <=> multiply by 8 */ 
    return u.f - x; /* 8*x - x == 7*x */ 
} 

Это два шага (один целое дополнение, один поплавок вычитание), своего рода, в зависимости от того, что вы считаете, как шаг. Учитывая, что C++ более или менее обратная совместимость с C, я считаю, что подобный трюк тоже должен быть там.

Обратите внимание, что этот хак обычно не дает правильных результатов для subnormal, бесконечных или NaN-входов, а также для входов, настолько больших по величине, что их умножение на 8 будет переполняться.

Корректировка кода для использования удвоений вместо поплавка остается как упражнение для чтения. (Подсказка: магическое число равно 52.)

+0

Необходимо также проверить соответствие платформы. На машине большого конца строка 'u.i + = (3 << 23);' становится просто 'u.i + = 3;'. –

+0

Поэтому было бы лучше использовать 'union {float f; uint8_t i [4]; } 'и' u.i [3] + = 3' или что-то в этом роде. –

Смежные вопросы