почему не работает не понимаю
- Войдите на сайт для отправки комментариев
Пт, 16/09/2016 - 05:14
void setup() { // put your setup code here, to run once: pinMode(A0,INPUT); pinMode(13,OUTPUT); Serial.begin(9600); } void loop() { // put your main code here, to run repeatedly: int s= analogRead(0) /4; Serial.println(s); int var=0.05076142*s-2; delay(1); Serial.print(var); delay(100); int e= analogRead(0) /4; Serial.print(e); int war=0.05076142*s-2; delay(10); Serial.print(war); if (var== war){ digitalWrite(13,LOW); } else { digitalWrite(13,HIGH); delay(1000); } }
добрый день,вот проблемма.програма получает на вход от сдвигового резистра разные данные данные(утвкрждает Serial)но диод не горит почемуто (( помогите где ошибка.зарание спасибо
прижмите А0 к земле - загорится.
погорячился... наоборот не загорится
сделайте var war типа float, не int
Печатайте не только s и e, а также var и war и всё поймёте.
Это писец. Грамотность нужна не только в написании СМС. Но и программ.
Простите
Простите, я может под вечер пятницы туплю не по детски, но объясните пожалуйста, что здесь не так собъявлением переменной?
То что судя по настройке предполагается ввод с А0 а реально идет с 0 )))
1) analogRead с 0 - это и есть с А0
2) ту настройку можно просто выбросить она ни на что не влияет вообще. Для analogRead она не нужна.
Да и qwone что-то там про объявление написал - я только не понял что.
Экая дивная плавучка посредь целочисленных операций. Кто возьмется предположить, в каком порядке компилятор будет делать приведение типов?
Кто возьмется предположить, в каком порядке компилятор будет делать приведение типов?
Я возьмусь. Или вопрос к ТС?
Вопрос обращен к любому, кому это покажется интересным. С удовольствием бы послушал ответ и тут я говорю совершенно серьезно. Лично мне такая конструкция режет глаз, отчего я и попытался обратить на нее внимание.
Ок, после хоккея вернусь и распишу
Простите, я может под вечер пятницы туплю не по детски, но объясните пожалуйста, что здесь не так собъявлением переменной?
Цикл он работает не один раз. И при каждом проходе создается переменная, которая к тому же считывает значение и делит на 4. И в конце прохода эта переменная уничтожается. Что бы создаться снова. Разумеется это будет работать. Я просто спутал со static, которую применяю в этих ситуациях.
Да, ладно, она в регистре создаётся - никаких проблем
int
var=0.05076142*s-2;
в каком порядке компилятор будет делать приведение типов?
Неявные преобразования типов всегда производятся непосредственно перед использованием переменной. Значит, здесь
1. s ->double (выглядит эквивалентно double tmp1 = s;)
2. вычисляется double tmp2 = tmp1 * s
3. 2 -> double (выглядит эквивалентно double tmp3 = 2;)
4. вычисляется double tmp4 = tmp2 - tmp3;
5. tmp4 -> int (выглядит эквивалентно int tmp5 = tmp4;)
6. выполняется var = tmp5;
Кстати, я не зра здесь писал эквиваленты - именно так определено в стандарте языка. Более того, явно сказано, что если в данном контексте объявление T tmp = ... недопустимо, то преобразование к типу T не производится. Тогда компилятор ищет к чему бы ещё преобразовать и если не находит - выдаёт ошибку.
Проверил примером в разных вариантах, пересчитал для контроля экселом, все сходится. Спасибо за рязъяснение.
А из каких соображений компилятор взялся приводить все к типу с плавающей точкой, а не наоборот к целочисленке?
PS. В первом пункте у вас описка.
А из каких соображений компилятор взялся приводить все к типу с плавающей точкой, а не наоборот к целочисленке?
Ну, здесь используются т.н. «обычные арифметические преобразования». Это понятие определено в п. 5.10 стандарта языка следующим образом:
(10.1) — если хотя бы один из операндов – член закрытого перечисления, преобразование не производится. Если при этом второй операнд имеет другой тип – фиксируется ошибка в выражении
(10.2) — если любой из операндов является long double, другой преобразуется к long double.
(10.3) — ИНАЧЕ если любой из операндов является double, другой преобразуется к double.
(10.4) — ИНАЧЕ, если любой из операндов является float, другой преобразуется к float.
(10.5) — ИНАЧЕ, к обоим операндам применяется «integral promotions» (определение «integral promotions» в свою очереь состоит из 7 пунктов, но общая идея там - всё, что полностью умещается в int преобразуется int, а что не умещается - к чему-нибудь более длинному). ЗАТЕМ к операндам применяются следующие правила:
Правила применяются именно в таком порядке. отсюда понятно, почему он преобразовал к double, а не к int.
Обратите внимание на п.п. 10.5.3 - 10.5.5: когда смешиваются знаковые и беззнаковые переменные, нужно много гороху сожрать, чтобы понять какого типа будет результат - больно много тонкостей. Отсюда и настоятельная рекоммендация программистам не смешивать знаковые и беззнаковые типы в одном выражении.
Это правило в купе с правилом «integral promotions» создают много тонкостей в преобразовании, которые знают далеко не все. Лучше избегать сложных неявных преобразований и преобразовывать всё самому, чтобы не было неожиданных сюрпризов.
Какое-то время неспешно размышлял над вышенаписанным, но в четкую структуру в мозгу все эти данные так и не сложились. Для себя пока вижу выход лишь в том, чтобы явно описывать все приведения типов в выражениях, где они используются. Громоздко, избыточно, но это хотя бы поможет избежать неприятных ошибок в вычислениях, если понимание того, как компилятор приводит типы, пока не дается.
За подробное изложение весьма вам признателен.
... понимание того, как компилятор приводит типы, пока не дается.
IMHO это понимание нужно только тем, кто преподает данный язык, либо тем, для кого он единственный. Во всех остальных случаях - явное приведение типов + не экономить на скобках.
Ну а компилдятор приводит типы (по крайней мере, должен приводить) в соответствии со стандартом языка. Нет у него права самостоятельно решать такие вопросы.
Общее правило: приводить более короткие типы к более длинным (вещественные считаются длиннее целых) и беззнаковые - к знаковым. Но в разных языках существуют свои тонкости.