DIYMan, посыпаю голову пеплом, по поводу двух ошибок я погорячился. Кстати, у меня в процитированной тобой строке ошибки тоже нет.
Итого, остается одна:
void swap1(byte & a, byte & b) {
byte tmp = a;
a = b;
b = tmp;
}
void swap2( byte &x, byte &y)
{
x ^= y;
y ^= x;
x ^= y;
}
void setup() {
// put your setup code here, to run once:
byte a = 5;
Serial.begin(115200);
Serial.println(a);
swap1(a,a);
Serial.println(a);
swap2(a,a);
Serial.println(a);
}
void loop() {
// put your main code here, to run repeatedly:
}
Вывод:
5
5
0
Вряд ли экономия одного байта стека оправдывает неэквивалентную замену.
Запускал здесь: http://cpp.sh/ - результат: обменивается, как надо. Подчёркиваю - это обмен ДВУХ переменных, а не одной, как в продемонстрированном тобой примере. Ибо если сделать так:
// Example program
#include <iostream>
#include <string>
void swap2( uint8_t &x, uint8_t &y)
{
x ^= y;
y ^= x;
x ^= y;
}
int main()
{
uint8_t b1 = 5;
std::cout << "Before: " << int(b1) << "-" << int(b1) << "\n";
swap2(b1,b1);
std::cout << "After: " << int(b1) << "-" << int(b1) << "\n";
}
То вывод будет другой, как у тебя. Нельзя применять микроскоп для забивания гвоздей - если сказано, что эта функция для обмена значениями двух переменных - то она для обмена значениями двух переменных, а то, что ты сделал - это вырожденный и, заметь, полностью бессмысленный случай - зачем менять что-то в одной переменной, если она и так уже имеет значение? Т.е. ты делаешь бессмыслицу, согласись ;)
Обмен методом XOR, кстати, был актуален, когда вычислительных ресурсов было очень мало, и экономили даже один байт. Сейчас, конечно, проще забить, и поюзать более мнемонически понятный вариант с промежуточной переменной. Однако и тут замечу: метод с XOR в хитрых случаях будет сильно выгодней одного байта на стеке, т.к. в случае типа данных размерностью, скажем, 100 байт - в твоём случае на стеке будут лишние 100 байт, в моём - не будут. Для такого типа данных в твоём случае потребуется реализация оператора присваивания, в моём - арифметического оператора, но по итогу - вариант с XOR выигрывает по размеру стека у варианта с промежуточной переменной, всегда.
Вот пример шаблонной функции swap:
// Example program
#include <iostream>
#include <string>
template<class T>
void swap2( T &x, T &y)
{
x ^= y;
y ^= x;
x ^= y;
}
int main()
{
uint64_t b1 = 5;
uint64_t b2 = 6;
std::cout << "Before: " << int(b1) << "-" << int(b2) << "\n";
swap2(b1,b2);
std::cout << "After: " << int(b1) << "-" << int(b2) << "\n";
}
Как видишь - там вообще любой тип данных может быть, к которому можно применить операторы ^ и =. В показанном выше примере в твоём случае на стеке будет уже лишних 8 байт. А теперь представь, что стек у тебя размером, скажем, байт в 16 - как считаешь, много это - 8 байт от стека в 16 байт, или нет? ;)
То вывод будет другой, как у тебя. Нельзя применять микроскоп для забивания гвоздей - если сказано, что эта функция для обмена значениями двух переменных - то она для обмена значениями двух переменных, а то, что ты сделал - это вырожденный и, заметь, полностью бессмысленный случай - зачем менять что-то в одной переменной, если она и так уже имеет значение? Т.е. ты делаешь бессмыслицу, согласись ;)
Давай вернемся к началу.
Для решения вполен конкретной задачи, сформулированной ТС, был предложен конкретный алгоритм, предполагающий тупой обмен в цикле одного элемента массива на ЛЮБОЙ другой. В т.ч. и на самого себя.
ТС не понял, что я подразумевал под именем swap в УКАЗАННОМ алгоритме, и я пояснил это примером.
После этого ты предложил СВОЮ замену реализацию функции swap, которая для данного алгоритма НЕ ПОДХОДИТ.
Т.е. ты своим советом превратил работающий алгоритм в неработающий.
А твои представления, что именно должна делать функция swap, а чего она делать не обязана, они, конечно, очень интересны, но к данной теме никакого отношения не имеют.
PS. И - да, если менять переменную бессмысленно (вне зависимости от того, по какой причине), то это совершенно не значит, что ее можно ПОРТИТЬ.
PPS. Опять же, я придерживаюсь мнения, что правильно написанная функция должна по возможности корректно работать с некорректными данными. Никто ведь не мешал написать, например, так (и байт из стека не расходуется):
void swap( byte &x, byte &y)
{
if(&x != &y) {
x ^= y;
y ^= x;
x ^= y;
}
}
Для решения вполен конкретной задачи, сформулированной ТС, был предложен конкретный алгоритм, предполагающий тупой обмен в цикле одного элемента массива на ЛЮБОЙ другой. В т.ч. и на самого себя.
Ок, принимается. Решается простой проверкой. Я не настаиваю на применении варианта с XOR, если ты заметил. Пусть юзает любой вариант, какой хочет. Свои мысли я высказал выше, про вольное обращение со стеком ты так ничего и не прокомментировал. Впрочем, и не стоит - я уже заметил, что тут проще привязаться к какому-нибудь несущественному моменту (ах, ну да, Дима должен за всех всё сразу писать, в том числе контроль всех возможных нюансов - именно для этого нужен форум), вместо того, чтобы уделить внимание конкретике. Ты пока - занимаешься первым, т.е. тупо мелешь воду в решете.
Вариант с XOR рабочий? Рабочий. До@баться и до столба можно, это очевидно. Умный - увидит, исходя уже из самой реализации XOR-swap, что там требуется ДВА разных адреса, и добавить махонькую проверочку, конечно, если ему хочется стек поэкономить, и юзать XOR-swap. Опять же - проверка нужна не везде, и впиху@вывать её прямо внутрь реализации swap - оверхед и признак херового программера, такое моё мнение: всё должно быть по-максимуму эффективно, и если внутри swap не нужна проверка - я её там и не писал. В некоторых, подчеркну, в НЕКОТОРЫХ случаях такая проверка нужна, случай ТС - тот самый. Но и в этом случае её не стоит по соображениям архитектуры пихать внутрь реализации - такое моё мнение номер два. Программист должен читать доку к API - это раз. Уметь читать код и понимать его особенности - это два. И не быть бездумной собачкой, считающей, что за него всё-всё делают - это три.
Зануда же - будет до@бываться до деталей, на которые мне, честно говоря, наплевать - я тут сопли за неумехами подтирать не намерен: не разбираются - this is Sparta!, следующий.
Надеюсь, я предельно ясно обрисовал свою позицию. Разговор окончен, далее в пустую полемику вступать не буду, делайте что хотите и как хотите, наплевать.
Рабочий - это когда работает всегда. А когда иногда - это не совсем рабочий.
Цитата:
Зануда же - будет до@бываться до деталей, на которые...
Вот именно.
В теме был сформулирован вопрос. На него дан ответ.
Тут ты вылез со своим "уточнением", причем в данном случае - неверным. Никто ничего не сказал.
Потом ты разместил псевдокод. Без проверки, без компиляции. Имеешь полное право. Я тоже, когда размещаю псевдокод, не пытаюсь его компилировать. Опять никто ничего не сказал.
Посетительница форума попыталась из твоего псевдокода сделать скетч. При этом не заметила твоих "неточностей" и насажала своих ошибок. Имеет полное право.
Я исправил код, упомянув про ошибки. Не называя имен. И тут ты взвился. Зачем? Это и есть твоя позиция?
Ты ж, вроде(?), говорил, что изучал программирование? Правда на Паскале, но это не страшно, моим первым языком тоже был Паскаль и ничего... ;). Тривиальные то задачки вроде должен знать? Или нет?
Так, по делу: своп без промежуточной переменной - это же разминочные олимпиадные задачки по программированию:
x = x + y; y = x - y; x = x - y;
или
x = x - y; y = x + y; x = y - x;
или XOR
x = x ^ y; y = x ^ y; x = x ^ y;
последнее решение всегда ценилось именно за красоту и отсутствие переполнений.
В С это оформляли макросом, который точно так же даст 0, если скормить ему одно имя два раза и чО?
Или сначал сделайте строку в которой есть всё, что надо и её выводите, или выводите несколькими print'ами. Ну или возьмите б-ку Printing (я тут где-то выкладывал на форуме), а там хоть потоком печатайте, хоть printf'ом
Или сначал сделайте строку в которой есть всё, что надо и её выводите, или выводите несколькими print'ами. Ну или возьмите б-ку Printing (я тут где-то выкладывал на форуме), а там хоть потоком печатайте, хоть printf'ом
Спасибо, сделал так
int randNum;
String text = "Number is ";
void setup()
{
Serial.begin(9600);
randomSeed(analogRead(0));
}
void loop()
{
randNum = random(1, 10);
Serial.println(text + randNum);
delay(200);
}
Евгений Петрович!
Счастья, любви, удачи, здоровья, бодрости, хорошего настроения!
strarbit, т.к. не дождался Вашего варианта, размещаю свой. Если посчитаете, что я что-то не то написал, поправьте:
Результат (сравните время выполнения):
DIYMan, посыпаю голову пеплом, по поводу двух ошибок я погорячился. Кстати, у меня в процитированной тобой строке ошибки тоже нет.
Итого, остается одна:
Вывод:
Вряд ли экономия одного байта стека оправдывает неэквивалентную замену.
Вряд ли экономия одного байта стека оправдывает неэквивалентную замену.
Свап ксором - дремучая фича. Только ты немного лукавишь - ты "обмениваешь" ОДНУ переменную ;) Вот код:
Запускал здесь: http://cpp.sh/ - результат: обменивается, как надо. Подчёркиваю - это обмен ДВУХ переменных, а не одной, как в продемонстрированном тобой примере. Ибо если сделать так:
То вывод будет другой, как у тебя. Нельзя применять микроскоп для забивания гвоздей - если сказано, что эта функция для обмена значениями двух переменных - то она для обмена значениями двух переменных, а то, что ты сделал - это вырожденный и, заметь, полностью бессмысленный случай - зачем менять что-то в одной переменной, если она и так уже имеет значение? Т.е. ты делаешь бессмыслицу, согласись ;)
Обмен методом XOR, кстати, был актуален, когда вычислительных ресурсов было очень мало, и экономили даже один байт. Сейчас, конечно, проще забить, и поюзать более мнемонически понятный вариант с промежуточной переменной. Однако и тут замечу: метод с XOR в хитрых случаях будет сильно выгодней одного байта на стеке, т.к. в случае типа данных размерностью, скажем, 100 байт - в твоём случае на стеке будут лишние 100 байт, в моём - не будут. Для такого типа данных в твоём случае потребуется реализация оператора присваивания, в моём - арифметического оператора, но по итогу - вариант с XOR выигрывает по размеру стека у варианта с промежуточной переменной, всегда.
Вот пример шаблонной функции swap:
Как видишь - там вообще любой тип данных может быть, к которому можно применить операторы ^ и =. В показанном выше примере в твоём случае на стеке будет уже лишних 8 байт. А теперь представь, что стек у тебя размером, скажем, байт в 16 - как считаешь, много это - 8 байт от стека в 16 байт, или нет? ;)
То вывод будет другой, как у тебя. Нельзя применять микроскоп для забивания гвоздей - если сказано, что эта функция для обмена значениями двух переменных - то она для обмена значениями двух переменных, а то, что ты сделал - это вырожденный и, заметь, полностью бессмысленный случай - зачем менять что-то в одной переменной, если она и так уже имеет значение? Т.е. ты делаешь бессмыслицу, согласись ;)
Давай вернемся к началу.
Для решения вполен конкретной задачи, сформулированной ТС, был предложен конкретный алгоритм, предполагающий тупой обмен в цикле одного элемента массива на ЛЮБОЙ другой. В т.ч. и на самого себя.
ТС не понял, что я подразумевал под именем swap в УКАЗАННОМ алгоритме, и я пояснил это примером.
После этого ты предложил СВОЮ замену реализацию функции swap, которая для данного алгоритма НЕ ПОДХОДИТ.
Т.е. ты своим советом превратил работающий алгоритм в неработающий.
А твои представления, что именно должна делать функция swap, а чего она делать не обязана, они, конечно, очень интересны, но к данной теме никакого отношения не имеют.
PS. И - да, если менять переменную бессмысленно (вне зависимости от того, по какой причине), то это совершенно не значит, что ее можно ПОРТИТЬ.
PPS. Опять же, я придерживаюсь мнения, что правильно написанная функция должна по возможности корректно работать с некорректными данными. Никто ведь не мешал написать, например, так (и байт из стека не расходуется):
Для решения вполен конкретной задачи, сформулированной ТС, был предложен конкретный алгоритм, предполагающий тупой обмен в цикле одного элемента массива на ЛЮБОЙ другой. В т.ч. и на самого себя.
Ок, принимается. Решается простой проверкой. Я не настаиваю на применении варианта с XOR, если ты заметил. Пусть юзает любой вариант, какой хочет. Свои мысли я высказал выше, про вольное обращение со стеком ты так ничего и не прокомментировал. Впрочем, и не стоит - я уже заметил, что тут проще привязаться к какому-нибудь несущественному моменту (ах, ну да, Дима должен за всех всё сразу писать, в том числе контроль всех возможных нюансов - именно для этого нужен форум), вместо того, чтобы уделить внимание конкретике. Ты пока - занимаешься первым, т.е. тупо мелешь воду в решете.
Вариант с XOR рабочий? Рабочий. До@баться и до столба можно, это очевидно. Умный - увидит, исходя уже из самой реализации XOR-swap, что там требуется ДВА разных адреса, и добавить махонькую проверочку, конечно, если ему хочется стек поэкономить, и юзать XOR-swap. Опять же - проверка нужна не везде, и впиху@вывать её прямо внутрь реализации swap - оверхед и признак херового программера, такое моё мнение: всё должно быть по-максимуму эффективно, и если внутри swap не нужна проверка - я её там и не писал. В некоторых, подчеркну, в НЕКОТОРЫХ случаях такая проверка нужна, случай ТС - тот самый. Но и в этом случае её не стоит по соображениям архитектуры пихать внутрь реализации - такое моё мнение номер два. Программист должен читать доку к API - это раз. Уметь читать код и понимать его особенности - это два. И не быть бездумной собачкой, считающей, что за него всё-всё делают - это три.
Зануда же - будет до@бываться до деталей, на которые мне, честно говоря, наплевать - я тут сопли за неумехами подтирать не намерен: не разбираются - this is Sparta!, следующий.
Надеюсь, я предельно ясно обрисовал свою позицию. Разговор окончен, далее в пустую полемику вступать не буду, делайте что хотите и как хотите, наплевать.
Вариант с XOR рабочий? Рабочий.
Рабочий - это когда работает всегда. А когда иногда - это не совсем рабочий.
Зануда же - будет до@бываться до деталей, на которые...
Вот именно.
В теме был сформулирован вопрос. На него дан ответ.
Тут ты вылез со своим "уточнением", причем в данном случае - неверным. Никто ничего не сказал.
Потом ты разместил псевдокод. Без проверки, без компиляции. Имеешь полное право. Я тоже, когда размещаю псевдокод, не пытаюсь его компилировать. Опять никто ничего не сказал.
Посетительница форума попыталась из твоего псевдокода сделать скетч. При этом не заметила твоих "неточностей" и насажала своих ошибок. Имеет полное право.
Я исправил код, упомянув про ошибки. Не называя имен. И тут ты взвился. Зачем? Это и есть твоя позиция?
Неочевидное можно, мне и самому интересно сделать, но только завтра, у меня ДР сегодня, пора к пьянке готовиться.
Ню, хоть и поздно заглянул, присоединяюсь к тостующим.))))
Странный ты какой-то, Андриано! ;)
Ты ж, вроде(?), говорил, что изучал программирование? Правда на Паскале, но это не страшно, моим первым языком тоже был Паскаль и ничего... ;). Тривиальные то задачки вроде должен знать? Или нет?
Так, по делу: своп без промежуточной переменной - это же разминочные олимпиадные задачки по программированию:
x = x + y; y = x - y; x = x - y;
или
x = x - y; y = x + y; x = y - x;
или XOR
x = x ^ y; y = x ^ y; x = x ^ y;
последнее решение всегда ценилось именно за красоту и отсутствие переполнений.
В С это оформляли макросом, который точно так же даст 0, если скормить ему одно имя два раза и чО?
или XOR
x = x ^ y; y = x ^ y; x = x ^ y;
последнее решение всегда ценилось именно за красоту и отсутствие переполнений.
а я первый сказал, что красиво )))
У меня второстепенный вопрос, почему не получается выводить в com-порт текст вместе с случайным числом ?
В выводе видны только обрывки текста.
Потому, что выводить можно только одно значение.
Или сначал сделайте строку в которой есть всё, что надо и её выводите, или выводите несколькими print'ами. Ну или возьмите б-ку Printing (я тут где-то выкладывал на форуме), а там хоть потоком печатайте, хоть printf'ом
Потому, что выводить можно только одно значение.
Или сначал сделайте строку в которой есть всё, что надо и её выводите, или выводите несколькими print'ами. Ну или возьмите б-ку Printing (я тут где-то выкладывал на форуме), а там хоть потоком печатайте, хоть printf'ом
Спасибо, сделал так
Ну, работать должно, но ради воробья расчехлять такую пушку, как String. Ладно, когда с памятью припрёт - переделаете.