Разберемся с одним из подходов к вводу данных из стандартного потока через класс java.util.Scanner . Сделаем это на примере простой задачи с очень полезного сайта e-olimp.com
Задача
Введите из стандартного потока одно число. В предположении, что это положительное двузначное целое число выведите в стандартный поток вывода каждую его цифру отдельно (через пробел). Порядок цифр менять не следует.
Тесты
Никаких специфических случаев в алгоритме не предполагается. Делаем три теста — самое маленькое число допустимого диапазона, самое большое и какое-нибудь значение из середины диапазона.
Вход | Выход |
10 | 1 0 |
99 | 9 9 |
54 | 5 4 |
Решение
Воспользуемся классом java.util.Scanner, чтобы ввести данные в формате целого числа. И вычислим обе его цифры.
Вывод цифр двухзначного целого числа
Java
class Main{ public static void main (String args) throws java.lang.Exception { java.util.Scanner i = new java.util.Scanner(System.in); int n = i.nextInt(); System.out.println(n / 10 + " " + n % 10); } }
class Main { public static void main (String args ) throws java . lang . Exception { java . util . Scanner i = new java . util . Scanner (System . in ) ; int n = i . nextInt () ; System . out . println (n / 10 + " " + n % 10 ) ; |
Пояснения
- Описываем переменную i типа java.util.Scanner и тут же присваиваем ей значение нового объекта этого класса. Конструктор изготавливает объект Scanner ‘а из стандартного потока ввода. Т.е. i становится надстройкой над стандартным потоком ввода. Это позволяет нам прочесть целое число, а не просто читать методом read () по одному байту.
- С помощью метода nextInt () читаем последовательность цифр и преобразуем её в целое число. Число запоминаем в переменной n.
- n / 10 — число десятков в числе. Десятков будет в десять раз меньше чем само число. Выполняется целочисленное деление — деление нацело.
- n % 10 — вычисляем остаток от деления на десять — число единиц — самая правая цифра числа.
- n / 10 + » » + n % 10 — вставляем между двумя целыми строку из одного пробела. В этом случае числа также преобразуются в строковое представление и все три строки сливаются — называется конкатенация строк. Так работает со строковыми данными операция «+».
Ускоряем ввод/вывод
При всем удобстве указанного подхода он довольно медленный и иногда задачи не заходят по времени. Значительно ускорить работу можно использовав StreamTokenizer и PrintWriter.
Это увеличит объем кода, но сэкономит время.
Ускорение ввода/вывода
Java
import java.io.*; import java.util.*; class Main { static StreamTokenizer in = new StreamTokenizer(new BufferedReader(new InputStreamReader(System.in))); static PrintWriter out = new PrintWriter(System.out); static int nextInt() throws IOException { in.nextToken(); return (int)in.nval; } public static void main(String args) throws java.lang.Exception { int n = nextInt(); out.println(n / 10 + " " + n % 10); out.flush(); } }
import java . io . * ; import java . util . * ; class Main { static StreamTokenizer in = new StreamTokenizer (new BufferedReader (new InputStreamReader (System . in ) ) ) ; static PrintWriter out = new PrintWriter (System . out ) ; static int nextInt () throws IOException { |
1. Основные арифметические операции
В следующей таблице перечислены основные арифметические операции, применяемые в языке Java:
Рассмотрим некоторые правила работы с арифметическими операциями:
- Выражения вычисляются слева направо, если не добавлены круглые скобки или одни операции имеют более высокий приоритет.
- Операции *, /, и % имеют более высокий приоритет чем + и -.
Пример 1. Арифметические операции над целочисленными значениями
Например, в этом коде, переменные a и b будут иметь разные значения:
Public class BasicIntMath { public static void main(String args) { int a = 4 + 5 - 2 * 3; int b = 4 + (5 - 2) * 3; System.out.println("a = " + a); System.out.println("b = " + b); } }
Результат выполнения:
A = 3 b = 13
- Операция унарного вычитания изменяет знак своего единственного операнда.
- Операция унарного сложения просто возвращает значение своего операнда. Она в принципе не является необходимой, но возможна.
Пример 2. Унарные операции сложения и вычитания
public class UnarySignOperation { public static void main(String args) { double a = -6; double b = +6; System.out.println(a); System.out.println(b); } }- Когда операция деления выполняется над целочисленным типом данных, ее результат не будет содержать дробный компонент.
Пример 3. Деление целочисленных чисел
public class IntDivision { public static void main(String args) { int a = 16 / 5; System.out.println(a); } }Результат выполнения этой программы:
- Операнды арифметических операций должны иметь числовой тип. Арифметические операции нельзя выполнять над логическими типами данных, но допускается над типами данных char , поскольку в Java этот тип, по существу, является разновидностью типа int .
Пример 4. Арифметические операции над переменными типа char
public class BasicCharMath1 { public static void main(String args) { char c = "n"; System.out.println(c); System.out.println(c + 1); System.out.println(c / 5); } }Результат выполнения:
N 111 22
Пример 5. Арифметические операции над переменными типа char
public class BasicCharMath2 { public static void main(String args) { char c1 = "1"; char c2 = "\u0031"; char c3 = 49; System.out.println(c1 + c2 + c3); } }Результат выполнения:
Оператор деления по модулю — обозначается символом %. Этот оператор возвращает остаток от деления первого числа на второй. При делении целого числа результатом будет тоже целое число.
Пример 6. Деление по модулю
public class DivisionByModule { public static void main(String args) { int a = 6 % 5; double b = 6.2 % 5.0; System.out.println(a); System.out.println(b); } }Результат выполнения:
1 1.2000000000000002
2. Составные арифметические операции с присваиванием
В Java имеются специальные операции, объединяющие арифметические операции с операцией присваивания. Рассмотрим следующее выражение:
А = а + 4;
B Java эту операцию можно записать следующим образом:
А += 4;
Составные операции с присваиванием позволяют не только уменьшить объем кода, но и позволяют выполнять автоматическое преобразование чего не делают обычные операции.
Пример 5. Составные арифметические операции с присваиванием
public class CompoundOperations { public static void main(String args) { int a = 1; int b = 2; int c = 3; a += 3; b *= 2; c += a * b; System.out.println(a); System.out.println(b); System.out.println(c); } }По приоритетности за унарными операторами следуют арифметические операторы. Эта группа включает в себя четыре наиболее распространённых оператора: сложение, вычитание, умножение, деление. И не только их. Существует также оператор деления по модулю, который обозначается знаком %. Арифметические операторы разделены на две группы. В первой, более приоритетной, группе находятся *, /, %. Во второй, соответственно, + и -.
Умножение и деление (* и /)
Операторы * и / выполняют умножение и деление над всеми примитивными числовыми типами и char. При делении на ноль возникает ArithmeticException .
Вы, наверное, недоумеваете, зачем я вам рассказываю про умножение и деление известное вам с первого класса. Однако, в программировании мы имеем дело с некоторыми ограничениями, связанными с представлением чисел в компьютере. Эти ограничения накладываются на все числовые форматы, от byte до double . Но наиболее заметны они для целочисленного типа int .
Если вы умножаете или делите два числа, результат вычисляется посредством целочисленной арифметики и сохраняется либо в int , либо в long . Если числа очень большие, то результат будет больше максимального числа, которое можно представить в этих числах. А значит, результат не сможет правильно закодироваться компьютером и не будет иметь смысла. Например, тип byte используется для представления чисел в диапазоне от -128 до 127. Если мы умножим 64 и 4, то результат 256, имеющий в двоичной записи 100000000 девять символов, будет закодирован, как 0, потому что byte использует лишь 8 символов.
Рассмотрим деление. Если вы делите в целочисленной арифметике, результат должен быть обязательно целочисленным. И значит, дробная часть будет потеряна. Например, 7/4 даёт нам 1.75, но в целочисленной арифметике это будет 1.
Таким образом, если вы имеете дело со сложными выражениями, вы можете выбирать последовательность умножений и делений. Но имейте в виду, что умножение может привести к переполнению , а деление - к потере точности . Народная мудрость считает, что выполнение сначала умножений, а потом делений в большинстве случаев выдаёт правильный результат. Рассмотрим пример:
1. int a = 12345, b = 234567, c, d;
2. long e, f;
3.
4. c = a * b / b; // должно равняться а=12345
5. d = a / b * b; // тоже должно равняться а=12345
6. System.out.println(“a is “ + a +
7. “\nb is “ + b +
8. “\nc is “ + c +
9. “\nd is “ + d);
10.
11. e = (long)a * b / b;
12. f = (long)a / b * b;
13. System.out.println(
14. “\ne is “ + e +
15. “\nf is “ + f);
Результат работы данного фрагмента выдаст следующее:
A is 12345
b is 234567
c is -5965
d is 0
e is 12345
f is 0
Пусть вас не смущают числовые значения данного примера. Важно то, что при выполнении умножения первым мы получили переполнение (c is -5965 ), когда закодировали его в тип int . Однако мы можем получить правильный результат, если закондируем его в более длинный тип, как, например, long . В обоих случаях применение первым деления будет катастрофическим для результата, независимо от длины его типа.
Деление по модулю %
Результат деления по модулю - остаток от деления. Например, 7/4 равно 1 с остатком 3. Поэтому 7%4 = 3. Обычно операнды имеют целочисленный тип, но иногда оператор применяется и к числам с плавающей точкой. Также следует знать некоторые особенности данного оператора, когда операнды отрицательные.
При негативных или дробных операндах правило такое: вычитайте правый операнд из левого до тех пор, пока последний не станет меньше первого. Примеры:
17%5 = ? 17-5=12>5; 12-5=7>5; 7-5=2<5. Значит 17%5 = 2
21%7? 21-7=14>7; 14-7=7=7; 7-7=0<7. Значит 21%7 = 0
7.6%2.9? 7.6-2.9=4.7>2.9; 4.7-2.9=1.8<2.9. Значит 7.6%2.9=1.8
Заметьте: знак результата (положительный или отрицательный) целиком и полностью определён знаком левого операнда, то есть делимого.
Когда деление по модулю производится над дробными числами, то суть этой операции состоит в том, чтобы вычесть делитель несколько раз. Результат может быть также дробным числом.
Простое правило для отрицательных операндов такое: отбросьте знак минуса от операндов, произведите деление по модулю с положительными операндами, а затем поставьте перед результатом минус, если левый операнд (делимое) был отрицательным.
Деление по модулю, как и нормальное деление, может выбросить исключение ArithmeticException , если делитель (правый операнд) ровняется нулю.
Большинство операций над примитивными типами выполняется не с помощью методов, а с помощью специальных символов, называемых знаком операции .
Операция присваивания
Присвоение переменной значения константы, другой переменной или выражения (переменных и/или констант, разделенных знаками операций), называется операцией присваивания и обозначается знаком "= ", например: x = 3 ; y = x; z = x; В Java допустимо многократное использование операции присваивания в одном выражении, например: x1 = x2 = x3 = 0 ; Эта операция выполняется справа налево, т.е. сначала переменной x3 присваивается значение 0 , затем переменной x2 присваивается значение переменной x3 (0), и, наконец, переменной x1 присваивается значение переменной x2 (0). Знаки операций, аргументами которых являются числа, разделяются на две категории: унарные (unary) знаки операций с одним аргументом и бинарные (binary) с двумя аргументами.Унарные операции
В Java определены следующие унарные операции:- унарный минус " - " – меняет знак числа или выражения на противоположный;
- унарный плюс " + " – не выполняет никаких действий над числом или выражением;
- побитовое дополнение " ~ " (только для целых) – инвертирует все биты поля числа (меняет 0 на 1 и 1 на 0);
- инкремент " ++ " (только для целых) – увеличивает значение переменной на 1;
- декремент " -- " (только для целых) – уменьшает значение переменной на 1.
Арифметические бинарные операции
В Java определены следующие арифметические бинарные операции :- сложение " + ";
- вычитание " - ";
- умножение " * ";
- деление " / ";
- вычисление остатка от деления целых чисел " % " (возвращает остаток от деления первого числа на второе, причем результат будет иметь тот же знак, что и делимое), например, результат операции 5%3 будет равен 2 , а результат операции (-7)%(-4) будет равен -3 . В Java операция может использоваться и для вещественных переменных (типа float или double).
Побитовые операции
- Побитовые операции рассматривают исходные числовые значения как поля битов и выполняют над ними следующие действия:
- установка бита в i -ой позиции поля результата в 1 , если оба бита в i -ых позициях операндов равны 1 , или в 0 в противном случае – побитовое И (" & ");
- установка бита в i -ой позиции поля результата в 1 , если хотя бы один бит в i -ых позициях операндов равен 1 , или в 0 в противном случае – побитовое ИЛИ (" | ");
- установка бита в i -ой позиции поля результата в 1 , если биты в i -ых позициях операндов не равны друг другу, или в 0 в противном случае – побитовое исключающее ИЛИ (" ^ ");
- сдвиг влево битов поля первого операнда на количество битов, определяемое вторым операндом (бит знака числа при этом не меняется) – побитовый сдвиг влево с учетом знака " << ";
- сдвиг вправо битов поля первого операнда на количество битов, определяемое вторым операндом (бит знака числа при этом не меняется) – побитовый сдвиг вправо с учетом знака " >> ";
- сдвиг вправо битов поля первого операнда на количество битов, определяемое вторым операндом (бит знака числа при этом также сдвигается) – побитовый сдвиг вправо без учета знака " >>> ".
Побитовое И
int x = 112 ; int y = 94 ; int z; z = x & y; // z=80: 00000000 00000000 00000000 01010000Побитовое ИЛИ
int x = 112 ; // x: 00000000 00000000 00000000 01110000 int y = 94 ; // y: 00000000 00000000 00000000 01011110 int z; z = x | y; // z = 126: 00000000 00000000 00000000 01111110Побитовое исключающее ИЛИ
int x = 112 ; // x: 00000000 00000000 00000000 01110000 int y = 94 ; // y: 00000000 00000000 00000000 01011110 int z; z = x ^ y; // z = 46: 00000000 00000000 00000000 00101110Сдвиг влево с учетом знака
int x = 31 , z; // x: 00000000 00000000 00000000 00011111 z = x << 2 ; // z = 124: 00000000 00000000 00000000 01111100Сдвиг вправо с учетом знака
int x = - 17 , z; z = x >> 2 ; // z = -5: 11111111 11111111 11111111 11111011Сдвиг вправо без учета знака
int x = - 17 , z; // x: 11111111 11111111 11111111 11101111 z = x >>> 2 ; // z = 1073741819 // z: 00111111 11111111 11111111 11111011
Комбинированные операции
В Java для бинарных арифметических операций можно использовать комбинированные (составные) знаки операций: идентификатор операция = выражение Это эквивалентно следующей операции: идентификатор = идентификатор операция выражение Примеры:- Выражение x += b означает x = x + b .
- Выражение x -= b означает x = x - b .
- Выражение x *= b означает x = x * b .
- Выражение x /= b означает x = x / b .
- Выражение x %= b означает x = x % b .
- Выражение x &= b означает x = x & b .
- Выражение x |= b означает x = x | b .
- Выражение x ^= b означает x = x ^ b .
- Выражение x <<= b означает x = x << b .
- Выражение x >>= b означает x = x >> b .
- Выражение x >>>= b означает x = x >>> b .
Операции сравнения
В Java определены следующие операции сравнения:- " == " (равно), " != " (не равно),
- " > " (больше), " >= " (больше или равно),
- " < " (меньше) " <= " (меньше или равно)
Булевские операции
Булевские операции выполняются над булевскими переменными и их результатом также является значение типа boolean . В Java определены следующие булевские операции:- отрицание "!" – замена false на true , или наоборот;
- операция И "&" – результат равен true , только, если оба операнда равны true , иначе результат – false ;
- операция ИЛИ " | " – результат равен true , только, если хотя бы один из операндов равен true , иначе результат – false .
- операция исключающее ИЛИ " ^ " – результат равен true , только, если операнды не равны друг другу, иначе результат – false .
Условная операция
Условная операция записывается в форме выражение-1?выражение-2:выражение-3 . При этом сначала вычисляется выражение выражение-1 , которое должно дать булевское значение, а затем, если выражение-1 имеет значение true , вычисляется и возвращается выражение-2 как результат выполнения операции, либо (если выражение-1 имеет значение false), вычисляется и, как результат выполнения операции, возвращается выражение-3 . Пример условной операции: x= n> 1 ? 0 : 1 ; Переменной x будет присвоено значение 0 , если n>1 (выражение n>1 имеет значение true) или 1 , если n≤1 (выражение n>1 имеет значение false).Старшинство операций
Операции в выражениях выполняются слева направо, однако, в соответствии со своим приоритетом. Так операции умножения в выражении y = x + z* 5 ; будет выполнена раньше, чем операция сложения, поскольку приоритет операции умножения выше, чем приоритет операции сложения. Приоритеты операций (в порядке уменьшения приоритета) в Java приведены в табл. 1.Круглые скобки повышают старшинство операций, которые находятся внутри них. Так, если в приведенное выше выражение вставить скобки: y = (x + z) * 5 ; то сначала будет выполнена операция сложения, а затем операция умножения. Иногда скобки используют просто для того, чтобы сделать выражение более читаемым, например: (x > 1 ) && (x <= 5 ) ;