2013-06-14 2 views
1

Для моей C вычисления, мне нужен тип знака (ассоциированный оператор является приемлемым), что можно сделать следующее:C: нужен тип «знак»

type sign_t = -1 | 0 | 1 

integer mult_sign(integer i, sign_t s) 
{ 
    switch (s) { 
    case -1: return -i; 
    case 0: return 0; 
    case 1: return i; 
    } 
} 

Разъяснение: Значение знака не известный во время компиляции!

В настоящем время, я использую C signed сек с целочисленным значением -1, 0, 1, соответственно, и операция представляет собой С умножением myint * mysign. Но мне интересно, имеет ли это последствия для производительности: для каждой операции с несколькими знаками используется аппаратное умножение, которое может быть медленнее, чем отрицание | установлен в 0 | не прикасайтесь.

Что было бы идеальным способом сделать это в C?

Что было бы идеальным способом, если бы мы убрали значение 0 из знаковых значений (поэтому допустимы только -1 и 1)?

Архитектура конкретных хаков/стандартного несоответствия очень хорошо, если вы скажете мне, где они находятся.

+3

Целочисленное умножение, скорее всего, будет быстрее, чем разветвление (что и подразумевает блок «switch») ... –

+1

Из того факта, что вы не указали на предсказание ветвей в своем кратком бессвязном представлении о производительности, я заключаю, что вы не следует беспокоиться о производительности на этом уровне (т. е. о микро-оптимизации). – delnan

+0

Конечно, я бы не хотел реализовывать это с ветвлением. Как вы видите, этот вопрос связан с битовыми манипуляциями. И да, я хочу сделать микро-оптимизацию. Программа http://spoj.com/problems/BULK, и уже у меня есть хороший алгоритм и одна из самых быстрых программ. –

ответ

11

Умножение кажется удивительным выбором.

Это очень ясно и кратко, и полагается только на основные (понятные) математические свойства целых чисел.

Вы не говорите много о своей среде исполнения, но на типичном настольном процессоре: умножение целочисленного числа было однократным в течение длительного времени. Так что сложно что-то ускорить.

Кроме того, умножение устраняет необходимость в ветви, чтобы «решить», что делать, что часто намного (намного) лучше, чем прыгать вокруг, чтобы что-то сделать «проще».

+0

Спасибо, это то, что я должен был знать: умножение - это один цикл. –

+0

Просто немного поддраться. Умножение - это не один цикл. Он имеет задержку между 3 и 7 (в зависимости от размера операнда и типа процессора). Но поскольку они конвейерны, они могут вычислить (теоретически) одно умножение каждого цикла, если операнды не зависят. На практике механизм отказа процессора может скрыть эту задержку в большинстве случаев, но в некоторых случаях это не так, и это может быть полезно. –

1

Это почти наверняка не узкое место в производительности. Просто используйте простой int.

Кстати, вы понимаете, что принятие отрицательного значения int min приведет к неопределенному поведению? Обычно вы просто получите то же самое, но вы, вероятно, хотите определить -fwrapv или что бы это ни было для обеспечения этого.

+0

Я не знал.Используется ли это только для '-myint' или также для' myint * s', где s не известно во время компиляции '-1'? –

0

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

В противном случае просто используйте умножение.

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