Простая ошибка умножения
Выполнение следующего кода всегда дает -511, в результате я выполнил много тестов, и кажется, что результаты верны от 0 * 0 до 181 * 181, помимо этого результаты ненормальны, я пробовал много типов для z переменная (int, long, float) безуспешно, есть идеи? Я использую Arduino Uno.
long z = 0;
void setup() {
Serial.begin(9600);
}
void loop() {
z = 255 * 255;
Serial.println(z);
delay(200);
}
@Huskarnov, 👍6
Обсуждение2 ответа
Предполагая, что длина long равна 4 байтам, это должно работать.
Однако, если по какой-то причине длинный тип имеет длину всего 2 байта, или (что более вероятно) вы использовали другой тип или существует какое-то неправильное определение/определение типа, и это длинный тип со знаком (по умолчанию, если вы не использовали ключевое слово без знака) , диапазон значений составляет от -32 768 до 32 767 и 255 * 255 = 65 025, что выходит за пределы диапазона.
Поэтому сначала можно попробовать использовать unsigned long
.
длинный — от -2 147 483 648 до 2 147 483 647., @Juraj
Если использовать unsigned long, результат будет: 4294966785., @Huskarnov
Ответ Квасмича правильный, @Juraj
@Юрай - там один короткий :p, @Jaromanda X
@Juraj Я думаю, что такая длина каким-то образом определяется как 2 байта., @Michel Keijzers
это не. Квасмич объясняет, @Juraj
Нет, это не ошибка. Вы используете выражение константы времени компиляции, которое имеет вид signed int
, если не указано иное. Поэтому вы можете представлять числа только от -32768 до 32767. Ваше вычисление 255 * 255 = 65025
выходит за пределы диапазона. Таким образом, вы видите переполнение. В стандарте C/C++ переполнение знаковых типов на самом деле является неопределённым поведением. Это означает, что компилятору разрешено делать что угодно: от отображения правильного ответа до остановки и возгорания. Только беззнаковые типы с известным размером, например uint16_t
, имеют четко определенное поведение при переполнении. Вам следует перевести вычисления правой части в беззнаковый тип следующим образом:
z = 255U * 255U;
Таким образом, вы сообщаете компилятору о своем намерении и не попадаете в «Землю неопределенного поведения».
@Juraj Верно, я думал, что он подписан как 16-битный, как int. Но последнее по-прежнему верно. Константы времени компиляции имеют знак int, то есть 16 бит. Итак, проблема заключается в правой части задания., @Kwasmich
«заворачиваться» звучит неправильно, но я знаю, о чем вы говорите, @Jaromanda X
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Подсказка: попробуйте «z = 255 * 255L;» или «z = 255 * (длинное) 255;», @Mikael Patel
Я сделал. @MikaelPatel Я действительно работал, не могли бы вы объяснить причину этого, и есть ли подобные случаи для других типов?, @Huskarnov
Эта «ошибка» стара, как программирование. Когда вы пишете «255», компилятор создает «целочисленную константу» со значением 255. Когда вы умножаете 255 на 255, вы умножаете две «целочисленные константы», и по соглашению результатом такого умножения является «целое число». Затем вы неявно приводите его к long при выполнении задания. Когда вы умножаете «255» на «255L», вы фактически умножаете «целочисленную константу» на «длинную константу», и результатом такого умножения является «длинная». Вы столкнетесь с аналогичной проблемой, когда напишете
float z = 1/5
, результат будет0
, поскольку в результате целочисленного деления получается целое число, которое позже преобразуется в число с плавающей запятой., @Filip FranikСсылка: https://gcc.gnu.org/wiki/avr-gcc — это вся информация, необходимая для компилятора AVR GCC. Все это связано с 1) диапазоном чисел «int» для данной цели и 2) оценкой компилятором постоянных выражений., @Mikael Patel
@MikaelPatel Вам следует отвечать на вопросы, а не писать их фрагменты в разделе комментариев., @pipe