|
Тип данных в Кейле |
|
|
|
Jun 10 2011, 05:18
|
Группа: Новичок
Сообщений: 5
Регистрация: 10-06-11
Пользователь №: 65 608

|
подскажите начинающему, к какому типу данных правильно отнести число 900 . Дело в том что кейл одинаково отрабатывает и "uint" и "uchar" с подобным числом и в железе все работает правильно, хотя , если я не ошибаюсь, это двухбайтовая величина и должна быть типа "short"
|
|
|
|
|
Jun 10 2011, 06:10
|
Группа: Новичок
Сообщений: 5
Регистрация: 10-06-11
Пользователь №: 65 608

|
поясню вопрос: с термометра ds18b20 считываются два байта данных о температуре, после мат обработки отсеивается часть данных(о знаке температуры), оставшаяся часть принимает описанный выше вид и заносится в переменную. Так при объявлении переменной какой тип данных использовать? пс. я считал, что указание типа обязывает компилятор резервировать соответствующее количество ячеек памяти...
|
|
|
|
|
Jun 10 2011, 06:46
|
Группа: Новичок
Сообщений: 5
Регистрация: 10-06-11
Пользователь №: 65 608

|
дополнение к вопросу. фрагмент кода:
tval=tval*(0.625);// return(tval);
после этой операции tval может принимать значение от 000 до 1200, далее идет сравнение с переменной содержащей число из этого диапазона.
извиняюсь, ошибка. Правильно от 0000 до 1200.
|
|
|
|
|
Jun 10 2011, 07:11
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(Desntal @ Jun 10 2011, 10:46)  после этой операции tval может принимать значение от 000 до 1200 Вы хотите правильно объявить переменную tval? А, какой диапазон значений этой переменной до этой операции? От 0 до 1920? Тогда - unsigned int... Применять операции с плавающей точкой в МК - очень расточительно. Достаточно привести 0.625 к виду 5/8 (деление на 8 целого = сдвиг вправо на 3), тогда Код tval= (5 * tval) >> 3;
|
|
|
|
|
Jun 10 2011, 10:55
|
Группа: Новичок
Сообщений: 5
Регистрация: 10-06-11
Пользователь №: 65 608

|
да, объяснить на пальцах трудно. может так понятнее:
...
unsigned ??? data tval;//???- это тип данных unsigned ??? data tUstavka; ... tval=tval*0.625; .... if(tval<=tUstavka) ...
сомнение вызвало то, что в описании типов данных в имеющейся литературе, размер типа uchar 255, а тип uint зависит от разрядности процессора, в данном случае для С51 8 разрядов, значит тоже 255, но здесь мне говорят что uint больше тысячи, запутали вконец... где истина?
|
|
|
|
|
Jun 10 2011, 11:20
|
Группа: Новичок
Сообщений: 5
Регистрация: 10-06-11
Пользователь №: 65 608

|
Палыч, спасибо, просмотрел файл, теперь все ясно можно смело использовать uint.
|
|
|
|
|
Jun 29 2011, 19:49
|

Местный
  
Группа: Свой
Сообщений: 213
Регистрация: 28-02-07
Из: Киев
Пользователь №: 25 744

|
Цитата(Палыч @ Jun 10 2011, 10:11)  Вы хотите правильно объявить переменную tval? А, какой диапазон значений этой переменной до этой операции? От 0 до 1920? Тогда - unsigned int... В корне неверно. Если unsigned int умножать на 0,625, то в результате всегда будет 0 Потому как (int)0,625 будет 0 Если нужно получать не 0, то нужно использовать float (или double, если нужно, и если оно поддерживается) Цитата(Палыч @ Jun 10 2011, 10:11)  Применять операции с плавающей точкой в МК - очень расточительно. Достаточно привести 0.625 к виду 5/8 (деление на 8 целого = сдвиг вправо на 3), тогда Код tval= (5 * tval) >> 3; Это правильно, без особой необходимости лучше плавучку на МК не использовать, здесь вам не тут, это не х86 с сопроцессором, однако. Тем более когда речь идёт об умножении на константу
|
|
|
|
|
Jun 30 2011, 08:59
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(koyodza @ Jun 29 2011, 23:49)  В корне неверно. Если unsigned int умножать на 0,625, то в результате всегда будет 0 Потому как (int)0,625 будет 0 Вот те - раз... В выражении tval=tval*0.625 , где tval целого типа, константа 0.625 - вещественная; значение tval приводится к вещественному типу; производится умножение двух вещественных; результат приводится к целому; присваивается tval...
|
|
|
|
|
Jul 11 2011, 20:51
|

Местный
  
Группа: Свой
Сообщений: 213
Регистрация: 28-02-07
Из: Киев
Пользователь №: 25 744

|
Цитата(Палыч @ Jun 30 2011, 11:59)  Вот те - раз... В выражении tval=tval*0.625 , где tval целого типа, константа 0.625 - вещественная; значение tval приводится к вещественному типу; производится умножение двух вещественных; результат приводится к целому; присваивается tval... Да, Вы правы, в данном случае происходит неявное приведение к double и обратно. Только вот оно надо? В любом случае подобных конструкций лучше избегать
|
|
|
|
|
Jul 12 2011, 08:48
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(demiurg_spb @ Jul 12 2011, 11:02)  Все современные компиляторы самостоятельно будут использовать сдвиг вместо деления когда это оправдано Возможно, но иногда удивляешся коду, который нагенерил "современный" компилятор... Цитата(demiurg_spb @ Jul 12 2011, 11:02)  (x*5)/8 совершенно равнозначно (х*5)>>3 А, вот тут я с Вами не согласен. Насколько я помню (поправьте, если я не прав): раставленные в выражении (x*5)/8 скобочки никак не определяют последовательность выполнения операций. Поскольку приоритеты операций * и / одинаковые, то выражение (x*5)/8 с точки зрения компилятора в соответствии со стандартом эквивалентно x*5/8 или даже x*(5/8). Компилятор вправе на этапе трансляции вычислить часть выражения, если операнды - константы. Но, поскольку 5/8 равно нулю, то можно получить результат далёкий от ожидаемого... При вычислении выражения (х*5)>>3 последовательность вычислений однозначно определена приоритетами.
|
|
|
|
|
Jul 12 2011, 09:33
|

неотягощённый злом
     
Группа: Свой
Сообщений: 2 746
Регистрация: 31-01-08
Из: Санкт-Петербург
Пользователь №: 34 643

|
Проверил живьём на максимальном уровне оптимизации выражение Код uint32_t x; x = (x*5)/8; превратилось в Код 0x08001C88 4C06 LDR r4,[pc,#24]; @0x08001CA4 0x08001C8A 6820 LDR r0,[r4,#0x00] 0x08001C8C EB000080 ADD r0,r0,r0,LSL #2 0x08001C90 08C0 LSRS r0,r0,#3 0x08001C92 6020 STR r0,[r4,#0x00] Всё как и ожидалось сначала умножил на 5 (хитро сложив и сдвинув), а потом поделил на 8 (сдвинув направо на 3). Стандарта в части скобочек не могу процитировать, но полагаю что scifi близок к истине.
--------------------
“Будьте внимательны к своим мыслям - они начало поступков” (Лао-Цзы)
|
|
|
|
|
Jul 12 2011, 09:43
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(scifi @ Jul 12 2011, 13:22)  нафиг скобки вообще нужны, если они ни на что не влияют? Я не утверждал, что скобки "ни на что не влияют". Например в выражении (х*5)>>3 они (скобки) очень даже "влияют". А, вот, в выражении (x*5)/8 компилятор вправе их игнорировать... Пример попроще: выражение (х+2)-1. Как Вы думаете: компилятор сгенерирует 1) выполнение двух операций или 2) преобразует в х+(2-1) и, соответственно, вычислит на этапе трансляции (2-1) и, в конце концов, получим х+1 ?
|
|
|
|
|
Jul 12 2011, 09:55
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Палыч @ Jul 12 2011, 13:43)  А, вот, в выражении (x*5)/8 компилятор вправе их игнорировать... Ну, если мне не верите, проверьте сами. По-вашему выражение (x*5)/8 даёт результат 0 вне зависимости от значения x. Это легко проверить. Или Вы хотите сказать, что результат выражения зависит от уровня оптимизации? Тогда это вообще нонсенс. Кому нужна оптимизация, коверкающая результат простейшего арифметического выражения? Не говоря уже о том, что это просто противоречит стандарту языка Си. Добавление: Да, в стандарте языка указаны случаи, в которых порядок вычисления не определён. Например, порядок вычисления аргументов функции. Или операндов побитового И или ИЛИ (& или |). Но (x*5)/8 - не тот случай. Стандарт чётко описывает, что сначала идёт умножение, а потом - деление (кстати, и без скобок тоже, по правилам приоритетов операторов). Причём умножение и деление происходят в "абстрактной машине". Что там нагенерит компилятор - его дело, лишь бы результат был бы такой же, как в "абстрактной машине". Как мы видели, он может нагенерить сдвиги и сложения. Или вообще подставить константу, если результат выражения известен на этапе компиляции.
|
|
|
|
|
Jul 12 2011, 10:18
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(demiurg_spb @ Jul 12 2011, 15:03)  Для себя уже давно доказал. Для разных компиляторов... То есть какой-то компилятор может "наплевать" на скобки? Какой? Upd. Проверил на IAR-е. Сложения и вычитания костант, идущие друг за другом даже за скобками он упрощает. Потому как переполнения на них не влияют. А умножения и деления нет.
Сообщение отредактировал GetSmart - Jul 12 2011, 10:27
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jul 12 2011, 10:27
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(GetSmart @ Jul 12 2011, 14:18)  То есть какой-то компилятор может "наплевать" на скобки? Какой? Как я понял, demiurg_spb и не намекает на то, что компилятор может наплевать на скобки. Напротив: Цитата(demiurg_spb @ Jul 12 2011, 13:50)  Когда можно упростить выражение без изменения сути, это будет сделано компилятором несомненно. В данном случае перестановка скобок (x*5)/8 -> x*(5/8) очень даже изменяет суть, а потому компилятору не разрешена. Что мы и пытаемся объяснить Палычу. Не соглашусь только, что компилятор применит оптимизацию "несомненно", так как видел немало тупых компиляторов.
|
|
|
|
|
Jul 12 2011, 10:49
|

Гуру
     
Группа: Свой
Сообщений: 2 399
Регистрация: 10-05-06
Из: г. Новочеркасск
Пользователь №: 16 954

|
Цитата(scifi @ Jul 12 2011, 13:55)  Ну, если мне не верите, проверьте сами. По-вашему выражение (x*5)/8 даёт результат 0 вне зависимости от значения x. Это легко проверить. Или Вы хотите сказать, что результат выражения зависит от уровня оптимизации? Нет, зависит от "уровня" трансляторописателей, вернее их понимания "духа и буквы" стандарта. Цитата(scifi @ Jul 12 2011, 13:55)  Стандарт чётко описывает, что сначала идёт умножение, а потом - деление (кстати, и без скобок тоже, по правилам приоритетов операторов). Тут с Вами не соглашусь. Приоритет всех мультипликативных операций (*, /, %) одинаков. Цитата(GetSmart @ Jul 12 2011, 14:18)  То есть какой-то компилятор может "наплевать" на скобки? В некоторых случаях - да, может "наплевать". Речь идёт о операциях с одинаковым приоритетом в скобках и за скобками. Нет времени искать точную формулировку в стандарте, но, по-памяти: "порядок выполнения операций может быть изменён, если это не приводит к изменению значения выражения". С учетом того, что при выполнении операций могут возникать всякие-разные "неприятности" (типа переполнения результата), то понятие "неизменный результат" становится очень расплывчатым, и тут - простор для трансляторописателей...
|
|
|
|
|
Jul 12 2011, 10:59
|
.
     
Группа: Участник
Сообщений: 4 005
Регистрация: 3-05-06
Из: Россия
Пользователь №: 16 753

|
Цитата(Палыч @ Jul 12 2011, 15:49)  Нет времени искать точную формулировку в стандарте, но, по-памяти: "порядок выполнения операций может быть изменён, если это не приводит к изменению значения выражения". Было такое. Но это исключительно когда нет скобок. Не выдумывайте свою интерпретацию Цитата(Палыч @ Jul 12 2011, 15:49)  В некоторых случаях - да, может "наплевать". Речь идёт о операциях с одинаковым приоритетом в скобках и за скобками. Но нельзя распостранять эти некоторые случаи на все, в силу собственного незнания этих случаев. Именно это и есть уровень вредных советов. Лучше приводить дословную формулировку. По логике, это можно делать, когда перепонения при исполнении операций не могут повлиять на результат. То есть то же, что и в школьной математике, но с учётом ограниченности (временных) переменных. Это подходит к сложениям/вычитаниям, лог операциям, но не относится к сдвигам, умнодениям/делениям.
--------------------
Заблуждаться - Ваше законное право :-)
|
|
|
|
|
Jul 12 2011, 11:19
|
Гуру
     
Группа: Свой
Сообщений: 3 020
Регистрация: 7-02-07
Пользователь №: 25 136

|
Цитата(Палыч @ Jul 12 2011, 14:49)  Нет, зависит от "уровня" трансляторописателей, вернее их понимания "духа и буквы" стандарта. То есть кто-то может неправильно понять стандарт и, соответвственно, написать компилятор с глюком. Спасибо за напоминание об это очевидном факте. Цитата(Палыч @ Jul 12 2011, 14:49)  Тут с Вами не соглашусь. Приоритет всех мультипликативных операций (*, /, %) одинаков. Я имел в виду в данном конкретном выражении: (x*5)/8. Цитата(Палыч @ Jul 12 2011, 14:49)  Нет времени искать точную формулировку в стандарте, но, по-памяти: "порядок выполнения операций может быть изменён, если это не приводит к изменению значения выражения". Нет нужды, я уже нашёл: Цитата The semantic descriptions in this International Standard describe the behavior of an abstract machine in which issues of optimization are irrelevant. ... In the abstract machine, all expressions are evaluated as specified by the semantics. An actual implementation need not evaluate part of an expression if it can deduce that its value is not used and that no needed side effects are produced (including any caused by calling a function or accessing a volatile object). Цитата(Палыч @ Jul 12 2011, 14:49)  С учетом того, что при выполнении операций могут возникать всякие-разные "неприятности" (типа переполнения результата), то понятие "неизменный результат" становится очень расплывчатым, и тут - простор для трансляторописателей... В случае с целыми беззнаковыми числами никакой расплывчатости нет: Цитата 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. Не разобравшись в ситуации, не давайте вредных советов. Вдруг неокрепшие умы всерьёз воспримут.
|
|
|
|
2 чел. читают эту тему (гостей: 2, скрытых пользователей: 0)
Пользователей: 0
|
|
|