почему не работает не понимаю

kiselev
Offline
Зарегистрирован: 02.07.2016
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)но диод не горит почемуто (( помогите где ошибка.зарание спасибо 

Gippopotam
Gippopotam аватар
Offline
Зарегистрирован: 12.09.2014

прижмите А0 к земле - загорится.

погорячился... наоборот не загорится

 

сделайте var war типа float, не  int

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Печатайте не только s и e, а также var и war и всё поймёте.

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Это писец. Грамотность нужна не только в написании СМС. Но и программ.

...
  pinMode(A0,INPUT); // обратите внимание A0
 ....
int s= analogRead(0) /4; // обратите внимание 0  и int  - объявление переменной внутри скобок и присвоение
...
int e= analogRead(0) /4; // обратите внимание 0  и int  - объявление переменной внутри скобок и присвоение
Serial.print(e);

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Простите

qwone пишет:

int s= analogRead(0) /4; // обратите внимание 0  и int  - объявление переменной внутри скобок и присвоение
...
int e= analogRead(0) /4; // обратите внимание 0  и int  - объявление переменной внутри скобок и присвоение

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

Logik
Offline
Зарегистрирован: 05.08.2014

То что судя по настройке предполагается ввод с А0 а реально идет с 0 )))

 

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

1) analogRead с 0 - это и есть с А0

2) ту настройку можно просто выбросить она ни на что не влияет вообще. Для analogRead она не нужна.

Да и qwone что-то там про объявление написал - я только не понял что.

a5021
Offline
Зарегистрирован: 07.07.2013

kiselev пишет:

int var=0.05076142*s-2;
[...]
int war=0.05076142*s-2;

Экая дивная плавучка посредь целочисленных операций. Кто возьмется предположить, в каком порядке компилятор будет делать приведение типов?

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

a5021 пишет:

 Кто возьмется предположить, в каком порядке компилятор будет делать приведение типов?

Я возьмусь. Или вопрос к ТС?

a5021
Offline
Зарегистрирован: 07.07.2013

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

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Ок, после хоккея вернусь и распишу 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

ЕвгенийП пишет:

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

Цикл он работает не один раз. И при каждом проходе создается переменная, которая к тому же считывает значение и делит на 4. И в конце прохода эта переменная уничтожается. Что бы создаться снова. Разумеется это будет работать. Я просто спутал со static, которую применяю в этих ситуациях.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

Да, ладно, она в регистре создаётся - никаких проблем

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

a5021 пишет:

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 не производится. Тогда компилятор ищет к чему бы ещё преобразовать и если не находит - выдаёт ошибку.

a5021
Offline
Зарегистрирован: 07.07.2013

Проверил примером в разных вариантах, пересчитал для контроля экселом, все сходится. Спасибо за рязъяснение.

А из каких соображений компилятор взялся приводить все к типу с плавающей точкой, а не наоборот к целочисленке?

PS. В первом пункте у вас описка.

ЕвгенийП
ЕвгенийП аватар
Offline
Зарегистрирован: 25.05.2015

a5021 пишет:

А из каких соображений компилятор взялся приводить все к типу с плавающей точкой, а не наоборот к целочисленке?

Ну, здесь используются т.н. «обычные арифметические преобразования». Это понятие определено в п. 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, а что не умещается - к чему-нибудь более длинному). ЗАТЕМ к операндам применяются следующие правила:

(10.5.1) — Если операнды уже получились одного типа – больше ничего не делаем.

(10.5.2) — ИНАЧЕ, если оба операнда знаковые (или оба беззнаковые), то тот, из них кто «короче» приводится к типу того, кто «длиннее» (int -> long и т.п.).

(10.5.3) — ИНАЧЕ, беззнаковый операнд «длиннее или равен по длине» другому операнду, то знаковый операнд преобразуется к типу беззнакового.

(10.5.4) — ИНАЧЕ, если тип знакового операнда может вместить все значения беззнакового, то беззнаковый операнд преобразуется к типу знакового операнда.

(10.5.5) — ИНАЧЕ, оба операнда преобразуются к беззнаковому типу, соответствующему типу знакового операнда.

Правила применяются именно в таком порядке. отсюда понятно, почему он преобразовал к double, а не к int.

Обратите внимание на п.п. 10.5.3 - 10.5.5: когда смешиваются знаковые и беззнаковые переменные, нужно много гороху сожрать, чтобы понять какого типа будет результат - больно много тонкостей. Отсюда и настоятельная рекоммендация программистам не смешивать знаковые и беззнаковые типы в одном выражении.

Это правило в купе с правилом «integral promotions» создают много тонкостей в преобразовании, которые знают далеко не все. Лучше избегать сложных неявных преобразований и преобразовывать всё самому, чтобы не было неожиданных сюрпризов. 

a5021
Offline
Зарегистрирован: 07.07.2013

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

За подробное изложение весьма вам признателен.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

a5021 пишет:

... понимание того, как компилятор приводит типы, пока не дается.

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

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

Общее правило: приводить более короткие типы к более длинным (вещественные считаются длиннее целых) и беззнаковые - к знаковым. Но в разных языках существуют свои тонкости.