реклама на сайте
подробности

 
 
13 страниц V  « < 10 11 12 13 >  
Reply to this topicStart new topic
> Детская ошибка
GetSmart
сообщение May 23 2016, 16:02
Сообщение #166


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



При преобразовании множества в многочлен теряется независимость. И простота логических операций. (Авто-)Расширение множества решается не созданием многочлена, а только наличием дополнительного бита у каждого операнда. Либо созданием правил расширения. Преобразование множества в многочлен этот дополнительный бит не порождает. А правила создания этого бита будут и в модели с множеством и в модели с многочленом. Во многих случаях принципиально иметь/работать с множеством, а не многочленом.

Сообщение отредактировал GetSmart - May 24 2016, 09:20


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aiwa
сообщение May 23 2016, 21:20
Сообщение #167


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Оказывается в С++11 структура "булевая алгебра" уже реализована посредством шаблона класса bitset.
С одной стороны получается даже излишнее: набор алгебр практически любой размерности, с другой стороны все "bitwise операции" в смысле буля реализованы только между членами класса.

Тогда топикстартовский пример становится корректным в смысле буля, если использовать явное преобразование.

~((bitset<16>)temp1) - инвертирование в смысле буля
~temp1 - ивертирование в смысле алгебры многочленов.

Остается дело за малым: bitset-ы размерности равных основным типам добавить к основным, при этом введя побитовые операции между типами bitset и основными, соответственно добавив функции а-ля "to_ulong" для этих размерностей - чтобы узаконить преобразования по умолчанию.
При этом, соответственно поделиться синонимами, так как это непозволительная роскошь попусту транжирить ключевые слова:
~, &, |, ^ - отдать основным битсетам, а comp, bitand, bitor, xor - оставить как есть - нынешним битвайзам.
Гуру языка, скорее всего, за такое изменение синтаксиса будет мучительно невыносимо, но зато начинающему большинству, еще не отягощенному знаниями стандарта такая реформа будет естественной.

Сообщение отредактировал aiwa - May 23 2016, 21:21
Go to the top of the page
 
+Quote Post
GetSmart
сообщение May 24 2016, 19:31
Сообщение #168


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Перечитываю себя и нахожу не совсем то, что хотел донести. От греха подальше поправлюсь.
Цитата(GetSmart)
(Авто-)Расширение множества решается не созданием многочлена, а только (в смысле только лишь) наличием дополнительного бита у каждого операнда.

(Авто-)Расширение множества решается, например, наличием дополнительного бита у каждого операнда.


Цитата(aiwa @ May 24 2016, 01:20) *
Оказывается в С++11 структура "булевая алгебра" уже реализована посредством шаблона класса bitset.

Огласите, пожалуйста, весь список где в С++ отличается результат тильды и побитовой инверсии. Если нет разницы, то зачем платить больше?
Применительно к целочисленным и enum операндам. Естественно, без переопределений тильды.

Сообщение отредактировал GetSmart - May 25 2016, 10:01


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
aiwa
сообщение May 25 2016, 01:25
Сообщение #169


Местный
***

Группа: Участник
Сообщений: 301
Регистрация: 13-12-15
Из: Харьков
Пользователь №: 89 682



Цитата(GetSmart @ May 24 2016, 22:31) *
Огласите, пожалуйста, весь список где в С++ отличается результат тильды и побитовой инверсии.

Список не предоставлю по причинам:
Во-первых я нигде не утверждал, что результат тильды в С++ отличается от побитовой инверсии.
Я только цитировал стандарт, что тильда определена как дополнение, что однозначно указывает принадлежность этой операции к набору операций двоичной арифметики многочленов.
Во вторых, также я не утверждал что компилятор компилирует не так как предписывает стандарт: компилятор строго ему следует.

Цитата(GetSmart @ May 24 2016, 22:31) *
Если нет разницы, то зачем платить больше?
Применительно к целочисленным и enum операндам. Естественно, без переопределений тильды.

Применительно к целочисленным и enum операндам, разница состоит в том, что приходится платить больше - набором дополнительных служебных слов и ухудшением из-за этого читабельности.
в обсуждаемом случае это для избавления от незванного подарка стандартом С++ в виде дополнительных поднятых 16-ти битах: (uint_16)(~var16)
Как другой, но более ресурсоемкий вариант: очистить результат маской, либо расширить вручную единичными разрядами.

В 98% случаев необходимость в побитовых операциях возникает не как к целочисленным (или enum) типам а именно как к набору бит.
98% я, конечно, написал от фонаря, 1% оставив разработчикам стандарта, другой 1% - прочитавшим стандарт для проверки, если вдруг захочется.
Косвенным доказательствам этого является введение в стандарт "по просьбам трудящихся" типа набора бит: bitset.

Появился третий вариант альтернативных действий, но тоже дополнительных: ~((bitset<16>)var16).

Но в 98% случаях нужно платить больше: набирать лишнее преобразование, захламляя текст, во втором - добавляя еще и команду, а в третьем вызывая еще и конструктор копирования.

При этом в оставшихся %2 случаях, текст кода остается "по умолчанию".

98% и 2% логично поменять местами.
Go to the top of the page
 
+Quote Post
vit496
сообщение Apr 25 2017, 19:30
Сообщение #170


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 27-09-07
Пользователь №: 30 876



Помогите пожалуйста восполнить пробел в познаниях языка.
почему компилятор может выбрасывать условие if(a==0)?

Код
void toggle_led ();

void main () {
  uint16_t i;
  uint8_t a;

  a = 5;
  for(i = 0; i < 500; i++) {
    a++;                                      
    if(a == 0) {
      toggle_led();  
    }
  }

  while(1);
}


ассемблер
Код
       NAME main
        PUBLIC main
        SECTION `.text`:CODE:NOROOT(1)
        THUMB
main:
??main_0:
        B.N      ??main_0

        END


Контроллер STM32F103, IAR ARM 6.10 (проверил и на 7.80), оптимизация по максимуму. toggle_led - внешняя функция, меняет состояние порта. Выбрасывается именно условие if(a==0), если поставить toggle_led без условия, то функция выполняется.
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Apr 26 2017, 05:25
Сообщение #171


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(vit496 @ Apr 25 2017, 22:30) *
Помогите пожалуйста восполнить пробел в познаниях языка.
почему компилятор может выбрасывать условие if(a==0)?

Видимо оптимизатор компилятора не учитывает возможность переполнения, и для него переменная a принимает значения от 5 до 500.

Вообще Ваш код нечитабельный и потенциально опасный, ибо на первый взгляд неочевидно, что a может принимать нулевое значение. В более сложном коде подобный подход это источник багов.
Go to the top of the page
 
+Quote Post
k155la3
сообщение Apr 26 2017, 05:55
Сообщение #172


Профессионал
*****

Группа: Свой
Сообщений: 1 123
Регистрация: 8-03-09
Из: Днепр
Пользователь №: 45 848



Цитата(vit496 @ Apr 25 2017, 22:30) *
Помогите пожалуйста восполнить пробел в познаниях языка.
почему компилятор может выбрасывать условие if(a==0)?


если Вам таки нужна переменная a вочтобытонистало

Код
__root  uint8_t a;

void main ()
{
  uint16_t i;
// uint8_t a;
  a = 5;
. . . .


Внимательно перечитайте все warn - запустите анализатор кода C-STAT StaticAnalysis (в меню Project).
Если оно есть в Вашем IAR/Target

Сообщение отредактировал k155la3 - Apr 26 2017, 05:56
Go to the top of the page
 
+Quote Post
Сергей Борщ
сообщение Apr 26 2017, 07:01
Сообщение #173


Гуру
******

Группа: Модераторы
Сообщений: 8 455
Регистрация: 15-05-06
Из: Рига, Латвия
Пользователь №: 17 095



QUOTE (Шаманъ @ Apr 26 2017, 08:25) *
Видимо оптимизатор компилятора не учитывает возможность переполнения
Настолько диких отступлений от стандарта IAR позволять себе не должен.
QUOTE
6.2.5 Types
9 The range of nonnegative values of a signed integer type is a subrange of the
corresponding unsigned integer type, and the representation of the same value in each
type is the same. A computation involving unsigned operands can never overflow,
because a result that cannot be represented by the resulting unsigned integer type is
reduced modulo the number that is one greater than the largest value that can be
represented by the resulting type

Вот оставить два вызова toggle_led() и пустой цикл мог бы запросто.


--------------------
На любой вопрос даю любой ответ
"Write code that is guaranteed to work, not code that doesn’t seem to break" (C++ FAQ)
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Apr 26 2017, 09:21
Сообщение #174


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Удалить if компилятор может как из-за условия, так и из-за тела. Условие обозначено вполне корректное. Даже volatile не требуется переменным. А вот содержимое toggle_led() не обозначено. Поэтому утвержтать, что ИАР неправ - преждевременно.


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
vit496
сообщение Apr 26 2017, 09:33
Сообщение #175


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 27-09-07
Пользователь №: 30 876



Цитата(Шаманъ @ Apr 26 2017, 09:25) *
Видимо оптимизатор компилятора не учитывает возможность переполнения, и для него переменная a принимает значения от 5 до 500.

если заменить присваивание a=5 на a=12 (или больше 12), то все работает как надо.

Цитата(k155la3 @ Apr 26 2017, 09:55) *
Внимательно перечитайте все warn

Никаких предупреждений нет.
Код
__root  uint8_t a;

с глобальной переменной работает правильно (без __root - тоже).



сам проект

Прикрепленные файлы
Прикрепленный файл  ux.7z ( 169.51 килобайт ) Кол-во скачиваний: 7
 
Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Apr 26 2017, 15:50
Сообщение #176


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(Сергей Борщ @ Apr 26 2017, 10:01) *
Настолько диких отступлений от стандарта IAR позволять себе не должен.

Так не факт, что это преднамеренно. Но судя по этому:
Цитата(vit496 @ Apr 26 2017, 12:33) *
если заменить присваивание a=5 на a=12 (или больше 12), то все работает как надо.

у IARа таки есть проблема.
Go to the top of the page
 
+Quote Post
vit496
сообщение Apr 26 2017, 19:10
Сообщение #177


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 27-09-07
Пользователь №: 30 876



Цитата(GetSmart @ Apr 26 2017, 12:21) *
Удалить if компилятор может как из-за условия, так и из-за тела. Условие обозначено вполне корректное. Даже volatile не требуется переменным. А вот содержимое toggle_led() не обозначено. Поэтому утвержтать, что ИАР неправ - преждевременно.

toggle_led ()
Код
{ GPIOA->ODR  ^= GPIO_Pin_0; }

Еще. Код ниже исправно выводит в порт значения переменной. А условие не выполняется, какой бы код в него не был бы помещен. Его просто нет в листинге.
Код
void main () {
  uint16_t i;
  uint8_t a;

  uart_init(57600);

  a = 5;
  for(i = 0; i < 500; i++) {
    a++;  
    printf("\ra=%d", a);                                    
    if(a == 0) {
      printf("\rxxxxxxx");  
    }
  }

  while(1);
}

в терминале:
Код
...
a=253
a=254
a=255
a=0
a=1
a=2
...


Go to the top of the page
 
+Quote Post
Шаманъ
сообщение Apr 27 2017, 05:59
Сообщение #178


Знающий
****

Группа: Участник
Сообщений: 758
Регистрация: 27-08-08
Пользователь №: 39 839



Цитата(vit496 @ Apr 26 2017, 22:10) *
Еще. Код ниже исправно выводит в порт значения переменной. А условие не выполняется, какой бы код в него не был бы помещен. Его просто нет в листинге.

Вроде уже объяснили - обычный глюк оптимизатора. Пишите понятные программы и они будут работать безглючно.

Как вариант замените a++ на a = (a+1) & 0xFF, ну и расскажите нам заработало ли...
Go to the top of the page
 
+Quote Post
GetSmart
сообщение Apr 27 2017, 07:07
Сообщение #179


.
******

Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753



Цитата(vit496 @ Apr 26 2017, 23:10) *
toggle_led ()
Код
{ GPIOA->ODR  ^= GPIO_Pin_0; }

Тут три идентификатора (хотя бы один из них) можно объявить так, что компилятор может иметь право их (иногда) удалять в процессе оптимизации. Вместе с чем-то ещё (проверкой условия). Причём неудаление в какой-то ситуации не означает, что компилятор не имеет право удалить в немного другой ситуации.

А ещё, неожиданно, может оказаться uint8_t шириной более 8 бит и ИАР окажется прав. Но по логу терминала видно, что он 8-битный.
И, если при изменении нач.значения a на 12 код создаётся правильный, то оправдать ИАР не получается. Может оптимизатор на этапе компиляции (почему-то) изменяет ширину переменной до 9 бит, при 12+500 получается как раз 0 в 9-битовой переменной.

PS
Архив не смотрел.

Сообщение отредактировал GetSmart - Apr 27 2017, 12:04


--------------------
Заблуждаться - Ваше законное право :-)
Go to the top of the page
 
+Quote Post
vit496
сообщение Apr 27 2017, 08:05
Сообщение #180


Участник
*

Группа: Участник
Сообщений: 20
Регистрация: 27-09-07
Пользователь №: 30 876



Цитата(Шаманъ @ Apr 27 2017, 09:59) *
Вроде уже объяснили - обычный глюк оптимизатора. Пишите понятные программы и они будут работать безглючно.

Как вариант замените a++ на a = (a+1) & 0xFF, ну и расскажите нам заработало ли...

нет, ни один из вариантов не помогает, пока переменная 8-ми битная.
условие a == 0x100 - то же не выполняется (на случай, если компилятор считает ее более 8 бит).
Помогает только использовать переменную 16-бит
Код
  uint16_t a=5;
  for(i = 0; i < 500; i++) {
    if(++a >= 0x100) {
      a = 0;
      .....

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

Сообщение отредактировал vit496 - Apr 27 2017, 08:14
Go to the top of the page
 
+Quote Post

13 страниц V  « < 10 11 12 13 >
Reply to this topicStart new topic
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 15:59
Рейтинг@Mail.ru


Страница сгенерированна за 0.01493 секунд с 7
ELECTRONIX ©2004-2016