вот правильное решение: ++a + (a--*++a).Посмотрел.Ну как может быть:4+(3*4)=20? Можно сделать ++a+(++a*++a),но условия не позволяют.Или я чего то не догоняю?
Игорь
27 уровень
ну ни фига не понятно
Обсуждается
Комментарии (37)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Глеб Team Lead
28 ноября 2024, 19:28
Спасибо :) Я понял.
Первый шаг 1: a=3, b=(сразу увеличивается а на 1, т.е. a=3+1)+(дальше ничего не меняется, т.е. a--*++a), после шага 1 а = 4;
Шаг 2. a=4, b=4+(сразу ставит a=4, а только потом a уменьшается на 1)*++a), после шага 2 а = 3;
Шаг 3: a=3, b=4+(4*(сразу увеличиватся а на 1, т.е. а=4)), после шага 3 а = 4;
Шаг 4: a=4, дальше просто считаем b, b=4+(4*4)=20
+2
Аделина Насирова
11 октября 2024, 07:38
5655
0
ArzamaS
1 апреля 2024, 06:55
так и не понятно в итоге, как это все работает, к сожалению....
0
ViiRusZx #3435538
7 апреля 2024, 16:17
int a = 3;
int b = ++a + (a-- * ++a);
1) - получается первая ++а(увеличится сразу до 4х) итог 4+(а-- + ++а)
2) - вторая а(которая а--) будет равна, так как на её место пойдет первая а, итог
4 + (4-- + ++а)
3) - третья а должна после инициализации уменьшится на 1(т.к. 4--) и увеличится на 1 (т.к. ++а)
итог 4+(4+ (4 которую уменьшаем на 1(по тому что она должна быть значением этого "4--"), потом увеличиваем на 1)
+3
Dana Timurova
23 мая 2023, 09:02
int a = 3;
int b = ++a + (a-- * ++a);
++a - тк ++ перед, будет сразу +1. получается а=4
а-- - тут будет 4, но след а будет -1. получается сейчас а=4, след а=3
++а - а был 3, но тк ++ стоит перед, будет +1. выходит а=4.
4+4*4
+10
ГоффMaster
17 мая 2023, 01:06
Логика простая. Сначала машина подставляет вместо переменных их значения, тупо слева направо, не обращая внимания на очерёдность выполнения арифметических операций, но с соблюдением пост- пре- де- и ин- криментов, и только потом, когда вместо переменных стоят числа, считает выражение, уже с соблюдением порядка операций.
+9
Anonymous #3473304
18 октября 2024, 07:26
Почему тогда в этом выражении получается 9 ?
int a = 3;
int b = (a-- * ++a);
System.out.println(b);
0
Денис Enterprise Java Developer
18 октября 2024, 07:44
Потому что 3 * 3 = 9, разве не очевидно? Если ты из тройки вычитаешь единицу, а потом добавляешь, сколько будет?
0
ГоффMaster
18 октября 2024, 07:59
Подробно:
слева направо, поехали, вместо первой а подставляется число три. Потом постдекримент, а становится равно двум. Следующее подставление, преинкримент, а сначала увеличивается на 1, получается 3, поэтому подставляется три. Потом как Денис написал, умножается. Скобки, кстати, не нужны.
0
hidden #3303140
18 октября 2024, 10:00
4 + 4 * 4.
1. Сначала вычисляется и подставляется ++a.
++a делает a равным 4 и возвращает (подставляет в выражение) изменённое значение, равное 4.
2. Потом вычисляется и подставляется постдекремент a--. Поскольку a в текущий момент уже равно 4 после первого действия, постдекремент возвращает текущее значение 4 и затем делает а, равным 3.
Принцип постинкремента/декремента заключается именно в том, что он сначала возвращает текущее значение, и только потом изменяет значение аргумента а. Поэтому он и называется «пост».
3. Текущее значение a равно 3. Поэтому при выполнении преинкремента ++а сначала значение a становится равным 4, и затем увеличенное значение возвращается (подставляется в выражение).
+1
Anonymous #3473304
18 октября 2024, 10:23
Я кажется разобрался. Скобочки - инкремент - мультипликативное действие (умножение) - пост декремент - инкремент - аддитивное действие (сложение). Тут очень важен приоритет пошаговый, а не какое то абстрактное представление, компилятор ничего не представляет, он именно пошагово выполняет код.
0
hidden #3303140
18 октября 2024, 11:16
Последнее предложение пытался понять, но не смог. Найди ниже спецификацию JLS, я приводил цитату.
Суть в том, что прежде чем вычислять всю арифметику, сначала вместо каждой функции подставляется результат. Это делается просто по порядку слева направо. А потом, когда все значения функций станут вычислены, начинается арифметика согласно правилам приоритета.
0
Anonymous #3473304
18 октября 2024, 17:51
int a = 3;
int b = a-- * ++a;
тут должно быть решение такое a = 4 до умножения и а = 3 после, но компилятор женщина, он рисует 9 в консоле. По моей логике 4 * 4 = 16, по вашей 3 * 4 = 12. А компилятор рисует 9. Тут нету логики.
0
Anonymous #3473304
18 октября 2024, 17:53
инкремент выполняется до умножения, а пост декремент после, так что там 4 * 4, а не 3 * 3.
0
Anonymous #3473304
18 октября 2024, 18:57
int a = 3;
int b = a-- * ++a;
System.out.println(b); //выводит 9, должен выводить 16. Если инкремент - умножение - декремент. Это баги какие то. ++a это 4, но никак не 3.
0
Денис Enterprise Java Developer
18 октября 2024, 19:21
Чувак, не тупи, тут и так разжевали уже как для моей бабушки. Не веришь людям - почитай спецификацию языка.
https://docs.oracle.com/javase/specs/jls/se7/html/jls-15.html#jls-15.7.2
когда ++ стоит справа от переменной это постинкремент, т.е. значение берётся, потом меняется
3++ участвующее в выражении это один хрен три при подсчете.
если же операция стоит слева то выполняется сначала она потом берётся значение.
--4 = 3
Именно по этому в твоём примере 3 * 3 = 9, и никаких багов тут нет.
Я понимаю что все непонятное пугает, но называть багами любую вещь которая тебе непонятна это как минимум глупо, язык писали люди неизмеримо умнее и талантливей чем ты когда либо станешь, а ты тут находишь баги в многолетнем труде :) За 20 лет никто не нашёл, а ты вот справился за вечер. Ну надо же хоть иногда в голову не только есть но и думать.
0
Anonymous #3473304
18 октября 2024, 20:24
где ты тут видишь 3++ ?
int a = 3;
int b = a-- * ++a;
0
Денис Enterprise Java Developer
18 октября 2024, 22:00
Ну хорошо, а какая разница?) все равно изначально берётся три, потом из него вычитается единица потом добавляется единица и снова берётся три. Как ни перекручивай, все равно для подсчёта перемножаются именно тройки. Вот так вот работают операции пре и пост инкремента\декремента
0
hidden #3303140
19 октября 2024, 06:28
Я понял, в чем ты заблуждаешься.
Ты взял изначально полное выражение ++a + (a-- * ++a), дальше тебе сказали, что в скобках будет 4*4, значит ты берёшь только скобки, а там вместо 16 получается 9. Это действительно так, потому что в скобках получится 16 только потому, что перед скобками есть ++а, которое первое слагаемое! Почитай ответы выше ещё раз.
Все функции вычисляются слева направо по порядку, плевать на скобки и приоритеты математических операторов. Первым подставляется аргумент и вычисляется ++а. После него а становится уже равно 4. И только после этого вычисляется значение аргументов в скобках.
Смотри, любой постинкремент или постдекремент ты можешь заменить на два действия:
Здесь b — это значение, которое подставится вместо а++.
А преинкремент представляет собой другую последовательность:
И тебе нужно подставить эти последовательности во всё выражение. Заменим по порядку все инкременты и декременты на переменные:
+1
Anonymous #3473304
19 октября 2024, 10:21
Дэнчик, до меня дошло. Оказывается постдекремент вычисляется раньше умножения, вот пример:
int a = 3;
int b = a-- + ++a + (a-- * ++a);
System.out.println(b);
в консоле 15. Почему? Да потому, что пост декремент (a--) за скобками вычислил значение переменной и вернул (3 - 1 = 2) двойку. А далее инкремент (2 + 1 = 3), потом пост декремент (3 - 1 = 2) и опять инкремент (2 + 1 = 3). В итоге мы получаем a = 3. Из этого получаем формулу
3 + 3 + (3 * 3) = 15. Скобки не имеют высшего приоритета, высший приоритет у функции, не важно, она пре или пост. Спасибо за помощь друзья :)
0
ABates
7 мая 2023, 11:27полезный
++3 + (3-- * ++3) = ++4 + (4-- * 4) =++4 +( 16 - 1) = ++4 + 15 = 5 + 15 = 20
+2
Алексей Михайлов
16 мая 2023, 13:04
как ты получил
++4 + (16 - 1)?
там должно быть
++3 + (16)
0
ABates
16 мая 2023, 16:45
смотри, сначала операция в скобках, перед умножением ++а = 3 увеличивается на 1 (везде где есть а в этом уравнении), после того как результат в скобках уже посчитана сначала первое а уже ранее увеличенное на 1 еще раз увеличивается на 1.
Или же что бы было понятно так (a + 1) + (a * (a + 1) - 1).
0
Алексей Михайлов
16 мая 2023, 18:19
не всё так просто
чему равно b?
+1
Роман Rime
16 июня 2023, 09:17
Не логично.
Сначала идут скобки: (3-- * ++3) == (4-- * 4) == 16 (после того, как скобки посчитали, происходит "а--" и, соответственно, "а" становится == 3.
далее левая часть выражения: ++3 + 16 == 4 + 16 == 20;
Выражение в скобках уже посчитано и из него не отнимается "-1", так как "-1" отнимается от "а" после завершения выражения в скобках.
0
hidden #3303140
16 июня 2023, 09:50
Сначала, перед тем как начать выполнять вычисление значения выражения, джава гарантирует, что известно значение каждого операнда этого выражения. Поэтому сначала не обращая внимания на скобки выполняются последовательно вычисления каждого операнда:
И потом уже после того, как все операнды были вычислены, джава-машина выполняет вычисление выражения:
Кстати, скобки тут не нужны, т.к. умножение и без них приоритетнее, чем сложение, а на порядок вычисления операндов скобки не влияют.
+2
Theb Cowe
26 сентября 2023, 13:45
У скобок приоритет выше, поэтому ++4 + (4-- * 4) = ++4 + (4 * 4) /* держим в уме -- */ = ++3 + 16 = 20. Если б скобок не было при такой же расстановке инкрементов/декрементов, получилось бы 5 + 5 * 5 = 30, а только после этого значение a уменьшилось бы на 1
0
hidden #3303140
26 сентября 2023, 19:13
Нельзя вообще писать ++4, это не валидная запись. Инкременты можно использовать только с целочисленными переменными. Это первое.
Второе - это собственно то, что уже написано в моём предыдущем комментарии, а именно- значение всех операндов вычисляется ДО начала вычисления значения всего выражения. Это никак не связано с наличием или отсутствием скобок. Это прописано в спецификации языка, читай JLS:
15.7.2. Evaluate Operands before Operation
The Java programming language guarantees that every operand of an operator (except the conditional operators &&, ||, and ? :) appears to be fully evaluated before any part of the operation itself is performed.
Скобки расставляют только приоритеты между арифметическими операциями. А вычисление значения выражения начнётся только после того, как выполнится вычисление значение для каждого из операндов в отдельности.
Другими словами, запись вида a++ – это не число, а некоторая функция, и прежде чем начать вычислять значение выражения, смотреть вообще где там скобки, программе требуется знать, какое значение эта функция (инкремент) возвращает. А эта функция по ходу своего вычисления меняет и текущее значение своего параметра (переменной a).
+1
Theb Cowe
2 октября 2023, 13:00
И в чём тогда отличие префиксной записи от постфиксной, если они одинаково работают?
0
hidden #3303140
2 октября 2023, 15:38
Где я написал, что они работают одинаково? Я написал, что обе функции вычисляются до начала вычисления арифметических выражений.
А отличие в том, что постфикс возвращает текущее значение аргумента и при этом увеличивает сам аргумент, а префикс увеличивает аргумент и затем возвращает его новое значение.
0
ABates
7 мая 2023, 11:23полезный
на самом деле все очень просто, если плюсы стоят перед переменной то данная переменная увеличивается на единицу перед дальнейшими операциями во всех местах в уравнении где она присутствует, а если после то сначала операция и только потом добавление или вычитание 1.
+5
Игорь
10 мая 2023, 08:04
Вот оно!то чего не догнал.Спасибо.
+1
Алексей Михайлов
6 мая 2023, 10:29полезный
изначальное значение в а какое?
если 3 то всё верно
сначала действие в скобках
из за префикса ++а сначала выполнится инкремент(причём инкремент всех а), умножение, а потом декремент и сложение
++а + (а-- * ++а) == 20
сначала инкремент в скобках а = 4
++3 + (3-- * ++3) == 20
потом умножение и декремент а = 3
++4 + (4-- * 4) == 20
потом опять инкремент и сразу сложение а = 4
++3 + 16 == 20
результат = 20
+3
Hawk Alexander
16 мая 2023, 12:13
с этим примером понятно, но вопрос почему в другом примере
int a = 3;
int b = --a + (a-- * ++a);
b получается 6 в компиляторе, как это возможно если считать в уме получается 18
--3 + (3-- * ++3)
--4 + (4-- * 4)
--3 + 16
2+16
0
Алексей Михайлов
16 мая 2023, 13:17
нужно смотреть приоритет операторов,
но по сути 6 ты можешь получить только 2*2+2 по другому никак
0
Алексей Михайлов
16 мая 2023, 14:04
попробовал поэкспериментировать и узнал для себя неприятный сюрприз
оказывается
т.е. постфиксный декремент и префиксный инкремент компенсируются, а вот такая запись
т.е. сначала срабатывают все декременты потом инкремент и толь после матеметические операции
у меня такое ощущение что компилятор шалит...
+1
hidden #3303140
17 мая 2023, 12:07
Всё правильно. Согласно 15.7.2 спецификации джавы у тебя, прежде чем приступить к вычислению значения выражения, вычисляются все значения операндов. Это происходит справа налево. Именно поэтому твоё выражение эквивалентно 2 + 2 * 2, и a после его вычисления также равно двум, т.к. последний унарный оператор был префиксом, т.е. не изменял значение a после вычисления.
0