Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
 
Рейтинг 4.55/11: Рейтинг темы: голосов - 11, средняя оценка - 4.55
foo();
885 / 587 / 222
Регистрация: 03.07.2013
Сообщений: 1,549
Записей в блоге: 2
1
.NET 4.x

Побитовые операции с целыми числами

22.02.2014, 23:29. Показов 2134. Ответов 22
Метки нет (Все метки)

Есть две переменные a и b. Обе задаются значениями в диапазоне [-1;1] включительно. Возможно ли какими нибудь операторами (всякими XOR и т.д.) заменить конструкцию
a == 0 ? b : a ;
Кажется что такое возможно, но не пойму как
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
22.02.2014, 23:29
Ответы с готовыми решениями:

Побитовые операции
Для двух символов реализовать операцию «И» два правых байт, получив таким образом значение для...

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

Логические побитовые операции
Привет изучаю как работают логические операции а именно (XOR) Вот написал програмку которая...

Побитовые операции с double
Нашел на msdn Почему так? А если мне надо побитово что-то с ним сделать? BitConverter'ом...

22
8347 / 4559 / 1784
Регистрация: 11.02.2013
Сообщений: 9,657
23.02.2014, 02:12 2
Т.е. если одна из переменных равна нулю, то использовать другую?
0
foo();
885 / 587 / 222
Регистрация: 03.07.2013
Сообщений: 1,549
Записей в блоге: 2
23.02.2014, 03:00  [ТС] 3
ViterAlex, да. Это возможно без условных операторов?
0
44 / 44 / 19
Регистрация: 20.01.2014
Сообщений: 87
23.02.2014, 03:06 4
по сути машина это делает при помощи алгебры логики примерно вот так:
Код
x = 1; // бит

// сравнение бита с нулем:
! (x ^ 1) // ^ - в данном случае означает логическое И (true только если оба оператора true). А оператор ! просто выполняет инверсию бита.
т.е сначала сравнивается 1 с 1, что дает 1 (true), по логике операции логического И, затем производится инверсия 1 (true) в 0 (false).
0
foo();
885 / 587 / 222
Регистрация: 03.07.2013
Сообщений: 1,549
Записей в блоге: 2
23.02.2014, 04:55  [ТС] 5
вроде у меня получилось:
a | (-a ^ b) & (a ^ b)
проверка
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
class Program
{
    static void Main(string[] args)
    {
        Func<int, int, int> expr = (a, b) =>
            a | (-a ^ b) & (a ^ b);
        Console.WriteLine(GenerateViriants().All(t => Check(t, expr))); \\True
        Console.ReadKey();
    }
    static IEnumerable<Tuple<int,int>> GenerateVariants()
    {
        var nums = Enumerable.Range(-1, 3);
        foreach (int a in nums)
            foreach (int b in nums)
                yield return new Tuple<int, int>(a, b);
    }
    static bool Check(Tuple<int, int> tpl, Func<int, int, int> expression)
    {
        int a = tpl.Item1, b = tpl.Item2;
        return (a == 0 ? b : a) == expression(a, b);
    }
}

такое выражение возможно укоротить?

Добавлено через 10 минут
dirtez0, позволю себе с Вами не согласиться
Цитата Сообщение от dirtez0 Посмотреть сообщение
^ - в данном случае означает логическое И
^ - аж никак ни логическое И, а исключающее ИЛИ!

Добавлено через 8 минут
dirtez0, Вашему вниманию предлагается:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
class Program
{
    static void Main(string[] args)
    {
        foreach (var t in GenerateVariants())
            Print((a, b) => a | b, '|', t);
        Console.WriteLine();
        foreach (var t in GenerateVariants())
            Print((a, b) => a & b, '&', t);
        Console.WriteLine();
        foreach (var t in GenerateVariants())
            Print((a, b) => a ^ b, '^', t);
        Console.ReadKey();
    }
    static IEnumerable<Tuple<int,int>> GenerateVariants()
    {
        var nums = Enumerable.Range(0, 2);
        foreach (int a in nums)
            foreach (int b in nums)
                yield return new Tuple<int, int>(a, b);
    }
    static void Print(Func<int,int,int> func, char f, Tuple<int,int> t)
    {
        int a = t.Item1, b = t.Item2;
        Console.WriteLine("{0} {1} {2} = {3}",
            a, f, b, func(a, b));
    }
}
Добавлено через 1 минуту
возвращаюсь к сабжу, можно ли укоротить выражение : a | (-a ^ b) & (a ^ b)
0
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 08:51 6
Цитата Сообщение от rattrapper Посмотреть сообщение
можно ли укоротить выражение : a | (-a ^ b) & (a ^ b)
Если в кол-ве буковок то a - a * a * b + b короче
1
Master of Orion
Эксперт .NET
6087 / 4943 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
23.02.2014, 16:14 7
rattrapper, только вот сравнение все равно быстрее, чуть ли не в один такт может сделать.
1
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 17:18 8
Цитата Сообщение от Psilon Посмотреть сообщение
только вот сравнение все равно быстрее
http://ideone.com/IPmG2G что я делаю не так?
1
Master of Orion
Эксперт .NET
6087 / 4943 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
23.02.2014, 18:14 9
pycture, неправильно считаете:
http://ideone.com/v9uCdG

забавно, что по времени одно и то же выходит
0
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 18:57 10
C#
1
2
3
 
Console.WriteLine("res1 = {0}", result[0].Average());
Console.WriteLine("res2 = {0}", result[0].Average());


ксати это еще более синтетический тест чем у меня

Добавлено через 18 минут
Моно как всегда работает как попало (видимо там компилятор в принципе ниче оптимизировать не в состоянии), а запуск под виндой
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
for (int i = 0; i < N; i++)
{
    var sw = Stopwatch.StartNew();
    int c = a1 == 0 ? b : a1;
    int d = a2 == 0 ? b : a2;
    sw.Stop();
    trash += c + d;
    result[0][i] = sw.ElapsedTicks;
 
    var sw2 = Stopwatch.StartNew();
    c = a1 - a1 * a1 * b + b;
    d = a2 - a2 * a2 * b + b;
    sw2.Stop();
    trash += c + d;
    result[1][i] = sw2.ElapsedTicks;
}
в большистве случаев показывает что арифметика незначительно быстрее перехода ( по крайней мере на моей машине)

Добавлено через 11 минут
Ну вот удалось привести моношную версию в чувство (путем избавления от бесполезных массивов) http://ideone.com/7zU8QK
Что в этом варианте я считаю неправильно ?
0
Master of Orion
Эксперт .NET
6087 / 4943 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
23.02.2014, 19:12 11
pycture,
ксати это еще более синтетический тест чем у меня
это называется кривая копи-паста.

Что в этом варианте я считаю неправильно ?
в этом - правильно Просто нужно смешанно считать, чтобы ликвидировать возможные аномалии, то есть в 1 цикле.

А так довольно интересный результат получился).

Ну вот удалось привести моношную версию в чувство (путем избавления от бесполезных массивов)
да я собирался исправить также, но пришлось переключиться на другую задачу (друг позвонил), но я рад, что мысли достойных сходятся

Добавлено через 3 минуты
rattrapper, кстати, задача случайно не из разряда "отсортировать по нескольким полям с помощью CompareTo"?

Добавлено через 58 секунд
pycture, энивей, хотя так и быстрее, лучше использовать понятную логику, а не магию и ловкость рук

Но это не умаляет ваших результатов.
2
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 19:37 12
Цитата Сообщение от Psilon Посмотреть сообщение
лучше использовать понятную логику
Здесь я полностью согласен.
Цитата Сообщение от Psilon Посмотреть сообщение
довольно интересный результат получился
Этому результату есть объяснение. В современных процессорах есть конвеер и предсказатель переходов. Если предсказатель промахивается конвеер вычищается, предвычесленные результаты в нем теряются и вычисления повторяются по другой ветке (с небольшими затратами по времени). При отсуствии условий и переходов, конвеер прет как танк и за счет этого может незначительно опережать вариант с переходом.
Но в условиях С# данный аспект почти не имеет практического применения, поэтому "лучше использовать понятную логику".
0
Эксперт .NET
15447 / 11711 / 3075
Регистрация: 17.09.2011
Сообщений: 19,603
23.02.2014, 19:38 13
Цитата Сообщение от pycture Посмотреть сообщение
Что в этом варианте я считаю неправильно ?
Даете слишком большое раздолье компилятору для оптимизации путем расчета некоторых значений на стадии компиляции.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
using System;
using System.Linq;
using System.Collections.Generic;
using System.Threading;
using System.Diagnostics;
 
namespace A
{
    class Program
    {
        private const int N = 1000000;
 
        private static void Main(string[] args)
        {
            long trash = 0;
            int a1, a2, b;
            var result0 = 0.0;
            var result1 = 0.0;
            int c, d;
            for (int i = 0; i < N; i++)
            {
                Randomize(out a1, out a2, out b);
 
                var sw = Stopwatch.StartNew();
                c = a1 == 0 ? b : a1;
                d = a2 == 0 ? b : a2;
                sw.Stop();
                trash += c + d;
                result0 += (double)sw.ElapsedTicks;
 
                var sw2 = Stopwatch.StartNew();
                c = a1 - a1 * a1 * b + b;
                d = a2 - a2 * a2 * b + b;
                sw2.Stop();
                trash += c + d;
                result1 += (double)sw2.ElapsedTicks;
            }
            Console.WriteLine(trash);
            Console.WriteLine("res1 = {0}", result0 / N);
            Console.WriteLine("res2 = {0}", result1 / N);
 
        }   // your code goes here
 
        static void Randomize(out int a1, out int a2, out int b)
        {
            a1 = r.Next(0);
            a2 = r.Next(0) + 1;
            b = r.Next(0) + 1;
        }
 
        static readonly Random r = new Random();
    }
}
Метод Randomize каждый раз "генерирует" те же самые значения (0, 1, 1), но компилятор уже не лезет с оптимизациями.

Было:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
  IL_001e:  call       class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
  IL_0023:  stloc.s    sw2
  IL_0025:  ldc.i4.1
  IL_0026:  stloc.3
  IL_0027:  ldc.i4.1
  IL_0028:  stloc.s    d
  IL_002a:  ldloc.s    sw2
  IL_002c:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
...
  IL_0045:  call       class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
  IL_004a:  stloc.s    sw
  IL_004c:  ldc.i4.1
  IL_004d:  stloc.3
  IL_004e:  ldc.i4.1
  IL_004f:  stloc.s    d
  IL_0051:  ldloc.s    sw
  IL_0053:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
Стало:
Assembler
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
  IL_002f:  call       class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
  IL_0034:  stloc.s    sw2
  IL_0036:  ldloc.1
  IL_0037:  ldloc.1
  IL_0038:  ldloc.1
  IL_0039:  mul
  IL_003a:  ldloc.3
  IL_003b:  mul
  IL_003c:  sub
  IL_003d:  ldloc.3
  IL_003e:  add
  IL_003f:  stloc.s    c
  IL_0041:  ldloc.2
  IL_0042:  ldloc.2
  IL_0043:  ldloc.2
  IL_0044:  mul
  IL_0045:  ldloc.3
  IL_0046:  mul
  IL_0047:  sub
  IL_0048:  ldloc.3
  IL_0049:  add
  IL_004a:  stloc.s    d
  IL_004c:  ldloc.s    sw2
  IL_004e:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
...
  IL_006a:  call       class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
  IL_006f:  stloc.s    sw
  IL_0071:  ldloc.1
  IL_0072:  brfalse.s  IL_0077
  IL_0074:  ldloc.1
  IL_0075:  br.s       IL_0078
  IL_0077:  ldloc.3
  IL_0078:  stloc.s    c
  IL_007a:  ldloc.2
  IL_007b:  brfalse.s  IL_0080
  IL_007d:  ldloc.2
  IL_007e:  br.s       IL_0081
  IL_0080:  ldloc.3
  IL_0081:  stloc.s    d
  IL_0083:  ldloc.s    sw
  IL_0085:  callvirt   instance void [System]System.Diagnostics.Stopwatch::Stop()
http://ideone.com/OJn3kl
0
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 19:56 14
Цитата Сообщение от kolorotur Посмотреть сообщение
Даете слишком большое раздолье компилятору для оптимизации путем расчета некоторых значений на стадии компиляции.
Стало
Ситуацию не меняет. Под виндой версия с арифметикой в 6-ти запусках из 10 опережает переход.
0
Эксперт .NET
15447 / 11711 / 3075
Регистрация: 17.09.2011
Сообщений: 19,603
23.02.2014, 20:03 15
Цитата Сообщение от pycture Посмотреть сообщение
Под виндой версия с арифметикой в 6-ти запусках из 10 опережает переход
У меня результат прямо противоположный.
Самый близкий результат — 1мс в пользу проверки, а так опережает на 7-8мс стабильно.

По ссылке тоже, но там не пойми какой компилятор и на чем выполнение.
0
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 20:11 16
Цитата Сообщение от kolorotur Посмотреть сообщение
Самый близкий результат — 1мс в пользу проверки, а так опережает на 7-8мс стабильно.
А в % это сколько?
У меня результат прямо противоположный
Это много от чего зависит, от процессора (и крутости его предсказателя), от системы, от текущей загрузки.
Можете попробывать убрать вызов Randomize из тела цикла
C#
1
2
3
4
5
6
7
8
9
for (int i = 0; i < N; i++)
{
    //Randomize(out a1, out a2, out b);
    a1 = r.Next(0);
    a2 = r.Next(0) + 1;
    b = r.Next(0) + 1;
 
    var sw = Stopwatch.StartNew();
....
Лишние переходы в этом тесте ему на пользу не идут.
0
Master of Orion
Эксперт .NET
6087 / 4943 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
23.02.2014, 20:16 17
pycture, Randomize не учитывается в stopwatch, поэтому он наоборот дает более чистые результаты.
0
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 20:17 18
Цитата Сообщение от Psilon Посмотреть сообщение
Randomize не учитывается в stopwatch
Дело не в stopwatch, дело в конвеере.

Добавлено через 1 минуту
Цитата Сообщение от Psilon Посмотреть сообщение
поэтому он наоборот дает более чистые результаты
И если не учитывается, то как дает более чистые результаты ?
0
Master of Orion
Эксперт .NET
6087 / 4943 / 905
Регистрация: 10.07.2011
Сообщений: 14,522
Записей в блоге: 5
23.02.2014, 20:18 19
При чем тут конвеер? Мы же пытаемся понять для любых чисел...

И да, все методы с телом менее 4 строк автоматически инлайнятся. Так что разницы не будет.
0
1193 / 586 / 88
Регистрация: 20.09.2012
Сообщений: 1,877
23.02.2014, 20:26 20
Цитата Сообщение от Psilon Посмотреть сообщение
При чем тут конвеер. Мы же пытаемся понять для любых чисел...
Причем конвеер я писал выше. А числа тут причем?
Цитата Сообщение от Psilon Посмотреть сообщение
И да, все методы с телом менее 4 строк автоматически инлайнятся
У меня не инлайнятся (net 4, studio 2013, x64, Release, [x]Optimize Code)
Код
		IL_0021: ldloca.s a1
		IL_0023: ldloca.s a2
		IL_0025: ldloca.s b
		IL_0027: call void A.Program::Randomize(int32&, int32&, int32&)
		IL_002c: call class [System]System.Diagnostics.Stopwatch [System]System.Diagnostics.Stopwatch::StartNew()
		IL_0031: stloc.s sw
		IL_0033: ldloc.1
		IL_0034: brfalse.s IL_0039
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
23.02.2014, 20:26

Побитовые операции - сдвиг
Вот код. Объясните пожалуйста,почему так ведёт себя последний цикл. Как-то он странно сдвигает. ...

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

Побитовые операции
С целью трассировки приложения предусмотреть вывод промежуточных результатов на каждом шаге. ...

Побитовые операции для вывода символа
форма символа кодируется последовательностью из 8 байтов. необходимо программно разложить каждый...

Побитовые операции над числами
Нашел вот задание помогите решить инфы нигде не могу найти по данной теме а=0xEB и b=0xB7 найти...

Побитовые операции с двоичными числами bash
Добрый день! Есть 2 числа в двоичной системе...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2021, vBulletin Solutions, Inc.