1 ПРОСТЕЙШАЯ ПРОГРАММА НА ЯЗЫКЕ ЯВА. ТИПЫ ДАННЫХ. КОНСТАНТЫ Рассмотрим программу на языке Ява, печатающую слова “Hello World!” в консольном режиме (т.е. в окне MS-DOS). Пример 1. 1. public class HelloWorldApp { 2. public static void main( String[] args ) { 3. System.out.println("Hello World!"); 4. //Здесь мы будем в дальнейшем помещать наш код 5. } 6. } В данный момент нет необходимости объяснять назначение всех строк программы, это станет ясно в дальнейшем. Укажем только, что строки 1, 2, 5, 6 являются обязательными для любого Ява - приложения. Команда в строке 3 System.out.println("Hello World!"); распечатывает строку, помещенную в кавычки. Знак «//» в четвертой строке указывает транслятору, что все, что следует после него, является комментарием, и должно быть проигнорировано транслятором. Наш комментарий указывает, что строки своего кода мы можем помещать между строк 2 и 5. Важным моментом является то, что файл, в котором помещается данная программа, должен иметь название HelloWorldApp и расширение java. Номера строк в тексте программы не нужны, они помещены в листинг для удобства. Рассмотрим более сложную программу, с помощью которой вычисляется площадь треугольника по формуле Герона. Пусть у нас есть треугольник со сторонами a, b и c. Полупериметр этого треугольника p равен 3 p a b c 2 , а площадь s равна s p p a p b p c . Данная программа будет содержать комментарии, описания, переменные, арифметические выражения, математические функции и печать результатов. Пример 2. 1. /*Вычисление площади по формуле Герона*/ 2. public class GeronApp { 3. public static void main(String[] args) { 4. double a, b, c, p, s; 5. 6. a = 3.; 7. b = 4.; 8. c = 5.; 9. 10. p = ( a + b + c )/2.; 11. s = Math.sqrt( p*(p-a)*(p-b)*(p-c) ); 12. System.out.println( "The area equals to "+s ); 13. } 14. } В строке 1 слова, стоящие между знаками «/*» и «*/», являются комментарием и игнорируются транслятором. Это еще один тип комментария. Между вышеуказанными знаками может стоять несколько строк текста. Комментарий, стоящий за знаком двойной черты «//» является однострочным. Комментарии служат для того, чтобы сделать программу более понятной. Строки 2, 3, 13, 14 являются обязательными для нашей программы, причем в строке 2 название GeronApp должно совпадать с названием файла, в котором хранится 4 программа. Строки 5 и 9 являются пустыми и разбивают программу на логические части. Пустые строки и отступы слева игнорируются транслятором, но улучшают читаемость программ. Строка 4 double a, b, c, p, s; означает, что переменные a, b, c, p и s имеют тип double, т.е. являются переменными с плавающей точкой двойной точности. В языке Ява все переменные должны быть описаны до того, как будут использованы. Описание переменной содержит указание типа, т.е. указание на то, какие значения может принимать переменная. Помимо double в языке Ява существует еще несколько примитивных типов, которые указаны в Приложении А. Имена переменных могут состоять из букв и цифр, причем начинаются с буквы. Большие и малые буквы различаются в названии переменных. Существует соглашение, что названия переменных начинаются с маленькой буквы, а все слова, входящие в название переменной с большой, например numberOfPoints. Имена переменных, как правило, выбирают осмысленными, что улучшает читаемость программы. В языке Ява существует ряд ключевых слов, которые нельзя использовать в качестве имен переменных. Они приводятся в Приложении Б. В строках 6-8 осуществляется инициализация переменных, т.е. присваивание им начальных значений. Чтобы указать, что a, b и с имеют тип double, их значения содержат десятичную точку, даже если значения не содержат дробной части, например, «а = 1.;». И описание переменных, и присваивание являются инструкциями. Каждая инструкция завершается точкой с запятой. Далее, в строках 10 и 11 осуществляются вычисления. Порядок действий с операторами «+, -, *, /» - такой же, как в арифметике. Скобки используются для определения порядка действий. Надо отметить, что в строке 11 нельзя опустить знак умножения между скобками. В строке 11 мы обращаемся к математической 5 функции Math.sqrt(), которая вычисляет квадратный корень. Математические операторы приводятся в Приложении В, а функции и константы в Приложении Г. В операторе вывода «System.out.println( "The area equals to "+s );» в строке 12 число, хранящееся в переменной s превращается в строку и «склеивается» со строкой «The area equals to». Рассмотрим вычисление полупериметра в строке 10. Знак равенства «=» является оператором присваивания. В языке Ява существуют также другие операторы присваивания. Воспользуемся следующим алгоритмом вычисления полупериметра. Вначале посчитаем периметр, затем, результат поделим на 2. Это можно осуществить с помощью следующего набора инструкций. p=(a+b+c); p/=2.; Последний оператор, «/=», означает, что содержимое p надо уменьшить в два раза, т.е., если p равно 4, то в результате операции «p/=2.;» p примет значение 2. Деление на два можно заменить умножением на 0.5, тогда вместо последней инструкции надо будет выполнить «p *= .5;», что означает увеличить содержимое p в 0.5 раз. Другими примерами оператора присваивания является «p+=2.;», что означает увеличить значение p на два, а также «p-=1.;», что означает уменьшить p на один. Рассмотрим еще один математический пример: вычисление площади окружности. Это делается с помощью формулы S = πr2. В начале нашей программы мы должны задать значения r и π. Пусть r равно единице. double r = 1.; double pi = 3.14159; double s = pi*r*r; Однако число π является константой и никогда не меняется в процессе вычислений. Поэтому к описанию π надо добавить слово final, чтобы запретить изменения этого числа в процессе вычислений, т.е. сделать его константой. По 6 соглашению названия констант в языке Ява набираются большими буквами. Если название константы состоит из нескольких слов, то в качестве разделителя слов используется символ подчеркивания «_». Наш фрагмент примет вид double r = 1.; final double PI = 3.14159; double s = PI*r*r; Из Приложения Г видно, что число π определено в математической библиотеке языка Ява. Нашу программу можно переделать, используя это. double r = 1.; double s = Math.PI*r*r; Задания 1. Набрать программу HelloWorldApp.java. из примера Оттранслировать 1. Сохранить программу ее в командой файле javac HelloWorldApp.java. При этом в текущей директории появится файл HelloWorldApp.class. Запустить программу из командной строки командой java HelloWorldApp, причем расширение в данном случае не нужно. Для повторного вызова команд из командной строки можно пользоваться стрелками. Дописать и запустить программу вычисления площади. 2. Вычислить значения выражений, если x = 1 и y = 2. 2.1. x2 y2 . Ответ: 2. Указание: часто используемые значения x2 и y2 2 2 x y 1 2 поместить во вспомогательные переменные. 2.2. 1 x x 2 2. Ответ: 2.5. 2.3. 1 x 1 x . Ответ: 4. 2.4. 1 x . Ответ: 1.414214. 3. Вычислить значения выражений. Сравнить с расчетами на калькуляторе. 7 3.1. a b 1.7 . Указание: описать переменные a, b, c, d, e, f как d c e f 0.5 переменные с двойной точностью. Инициализировать переменные какими – либо значениями. 3.2. sin a b a . Указание: тригонометрические функции принимают b cos b аргумент в радианах. 3.3. x 3.4. x2 1 sin 2 x y 1 1 sin x 2 . . 4. Вычислить значения выражений. Сравнить с расчетами на калькуляторе. 4.1. 5/9. 4.2. 1 . 2 1 4 4.3. x 1 2 y 3 10 4 5 . 2 УСЛОВНЫЙ ОПЕРАТОР. БЛОКИ Решим следующую задачу. Даны два числа, x и y. Если первое больше второго по абсолютной величине, то необходимо уменьшить первое в пять раз. Напишем программу. Пример 3. public class CondApp { 8 public static void main( String[] args ) { double x, y; x = -3.; y = 2.; if( Math.abs( x ) > Math.abs( y ) ) x /= 5.; System.out.println( "x = " + x ); } } Мы воспользовались условным оператором if(), который проверяет условие в скобках. Если оно истинно, то выполняется следующий за if оператор, в противном случае этот оператор игнорируется. В нашем примере модуль x больше модуля y, поэтому x делится на пять. Если бы в качестве x мы выбрали 0.8, то значение x осталось бы без изменений. В условном операторе используются выражения типа boolean. Переменные типа boolean могут принимать два значения - true или false. В качестве условий используются отношения типа x равно y или x больше нуля. В качестве оператора равно в языке Ява используется двойной знак равенства «==» в отличие от одинарного равенства, означающего присваивание. В качестве операторов больше или равно и меньше или равно используются соответственно «>=» и «<=». В качестве оператора «не равно» используется «!=». Все операторы сравнения возвращают результат типа boolean. Рассмотрим другой пример, пусть даны два числа, x и y, и надо напечатать наибольшее из них. Напишем программу. Пример 4. public class CondApp2 { public static void main( String[] args ) { 9 double x, y, max; x = 1.; y = 3.; if( x > y ) max = x; else max = y; System.out.println( "max = " + max ); } } В нашей программе проверяется условие «x > y». Если это условие выполняется, то переменной max присваивается значение, хранящееся в переменной x. В противном случае, переменной max присваивается значение, хранящееся в переменной y, о чем говорит инструкция присваивания, следующая за else. Рассмотрим следующий пример. Пусть нам надо вычислить значение функции x, x 2 y 2,2 x 3 . x 5, x 3 Напишем программу. Пример 5. public class CondApp3 { public static void main( String[] args ) { double x, y; x = 6.; if( x < 2. ) 10 y = x; else if( x <= 3. ) y = 2.; else y = 5. - x; System.out.println( "y = " + y ); } } В общем случае можно использовать сколько угодно конструкций else if. Проанализируем, как работает наша программа. Вначале проверяется первое условие «x<2». Если это условие выполняется, то выполняется оператор, следующий за if, в противном случае этот оператор игнорируется и осуществляется переход к проверке следующего условия, «x <= 3». В принципе, можно осуществлять проверку на выполнения двух условий, «x >= 2» и «x <= 3», одновременно. Это делается с помощью оператора логического и «&&», например, «if( (x >= 2) && (x <= 3) )», однако в этом нет необходимости. Если окажется, что x меньше двух, то вначале выполнится оператор присваивания «y = x;», все остальные части составного условного оператора будут проигнорированы, и будет распечатано значение функции. Если значение x лежит между 2 и 3, то первое условие не будет истинным, и следующий за ним оператор присваивания будет проигнорирован. Т.к. наше значение x меньше либо равно трем, то второе условие окажется выполненным, что приведет к выполнению оператора присваивания «y = 2.;», а затем к перескоку к печати результата. Из формулы для функции y видно, что третье условие выполняется, если первые два не выполняются, поэтому сравнение опущено. Если значение x больше 3, то выполняется оператор присваивания «y = 5. - x;», а затем осуществляется печать результата. 11 В условном операторе после if и else можно помещать по одному оператору (выражению, заканчивающемуся точкой с запятой). Фигурные скобки «{}» используются для объединения описаний и инструкций в одну составную инструкцию, так называемый блок. Рассмотрим пример. Пусть нам надо решить квадратное уравнение ax 2 bx c 0 . Мы должны вначале вычислить дискриминант уравнения d b 2 4ac . Если d 0 , то уравнение будет иметь действительные корни, в противном случае – комплексные. Рассмотрим пример 6. public class CondApp4 { public static void main( String[] args ) { double a, b, c, d; a = 1.; b = 2.; c = -3.; d = b*b - 4*a*c; if( d >= 0. ) { System.out.println( "x1 = " + (Math.sqrt( d ) - b)/(2.*a) ); System.out.println( "x1 = " + (-Math.sqrt( d ) - b)/(2.*a) ); } else System.out.println( "There're no real roots" ); } } 12 Здесь мы объединили две инструкции вычисления действительных корней в блок. Если бы мы опустили фигурные скобки, то к оператору if относилась бы только инструкция вычисления первого корня. Задания. 1. Написать программы, печатающие значения функций. x 2 ,2 x 2 1.1. y . Указание: программу написать тремя 4 , в противном случае способами. С использованием оператора логического и &&, когда условия выполняются одновременно, с использованием оператора логического или ||, когда выполняется одно из условий, и без использования вышеуказанных операторов. 1.2. 0, x 0 y x ,0 x 1 . x4 , x 1 2. Даны три числа, x, y и z. Найти: 2.1. max(x+y+z, xyz)+3. 2.2. min(x2+y2, y2+z2)-4. Указание: min(a,b) и max(a,b) – минимальное и максимальное из двух чисел a и b. 3. Дано три числа a, b и c. Выяснить, верно ли, что a<b<c. Ответ вывести в текстовой форме: «верно» или «неверно». 4. Дано три числа a, b и c. Удвоить каждое из чисел, если a b c и заменить числа их модулями в противном случае. 5. Даны два числа, x и y. Если x и y отрицательны, то каждое значение заменить его модулем. Если отрицательно только одно из чисел, то оба значения увеличить на 0.5. Если оба значения неотрицательны, то оба значения увеличить в 10 раз. 13 3 ЦИКЛЫ При решении задач вычислительной физики часто возникает необходимость проводить какие-то однотипные вычисления. Пусть, например, мы хотим составить таблицу, переводящую температуру в градусах Цельсия в абсолютную температуру. Это делается с помощью формулы T(K)=tº(C) + 273.15. Рассмотрим программную реализацию. Безусловно, надо ввести константу, равную 273.15, которая прибавляется к температуре t. Обозначим ее DELTA. Также необходимо задать начальное и конечное значения интервала температур, для которого осуществляется перевод в абсолютную температуру, и шаг, с которым вычисляется температура. Пример 7. public class LoopsApp { public static void main( String[] args ) { final double DELTA = 273.15; final int LOWER = -99,//Нижняя граница температур UPPER = 100,//Верхняя граница температур STEP = 20;//Шаг double tempr; tempr = LOWER; while( tempr <= UPPER ) { System.out.println( "t,C = " + tempr + "\tT,K = " + (tempr + DELTA) ); tempr += STEP; 14 } } } В начале программы мы описали все переменные и константы, а также присвоили им начальные значения. После этого следует оператор цикла, который осуществляет печать таблицы. Оператор while работает следующим образом. Вычисляется условие в скобках. Если оно истинно, то выполняется тело цикла, стоящее в фигурных скобках. После этого опять происходит проверка условия, и если оно истинно, снова выполняется тело цикла. Так происходит, пока условие будет выполняться. Как только условие станет ложным, т.е. tempr станет больше UPPER, то произойдет выход из цикла и, в нашем случае, выход из программы. Если при первой проверке условия оно окажется ложным, то тело цикла не выполнится ни разу. Обратите внимание на эскейп – последовательность «\t» в операторе вывода. Данная последовательность называется табуляцией и указывает, что вывод следующего за ним символа надо сдвинуть на несколько позиций вправо. Еще одна полезная эскейп – последовательность «\n» приводит к переносу строки. Все, что за ней следует, печатается с новой строки. Для форматирования чисел, т.е. превращения их в строку с заданным числом цифр после запятой, существует тип данных DecimalFormat из пакета java.text. С помощью специальных значков, 0 - обязательная цифра, # - цифра или ничего, задается шаблон. При выводе результатов вызывается метод format() класса DecimalFormat, и этому методу передается число, которое надо отформатировать. В результате, на печать выводится отформатированная строка, например DecimalFormat df1 = new DecimalFormat("000.00"), df2 = new DecimalFormat("#.##"), df3 = new DecimalFormat("#.#E0"); 15 double d = -1.5383; System.out.println( df1.format(d) + '\t' + df2.format(d) + '\t' + d3.format(d) ); В результате получаем: -001.54 -1.54 -1.5E0 Для того чтобы использовать форматирование чисел, надо включить пакет, в котором находится код функций форматирования. Это делается строкой, размещаемой в начале файла «import java.text.*;». Перепишем пример 7 так, чтобы в значении абсолютной температуры выводилось только два знака поле запятой. Изменения в программе выделены жирным шрифтом. Пример 7а. import java.text.*; public class LoopsApp2 { public static void main( String[] args ) { final double DELTA = 273.15; final int LOWER = -99,//Нижняя граница температур UPPER = 100,//Верхняя граница температур STEP = 20;//Шаг double tempr; DecimalFormat df = new DecimalFormat("#.##"); tempr = LOWER; while( tempr <= UPPER ) { System.out.println( "t,C = " + tempr + "\tT,K = " + df.format(tempr + DELTA) ); tempr += STEP; 16 } } } Одну и ту же задачу можно выполнить различными способами. В нашем случае, можно вместо цикла while использовать цикл for. Программа будет иметь вид. Пример 8. import java.text.*; public class LoopsApp3 { public static void main( String[] args ) { final double DELTA = 273.15; final int LOWER = -99,//Нижняя граница температур UPPER = 100,//Верхняя граница температур STEP = 20;//Шаг DecimalFormat df = new DecimalFormat("#.##"); for( int tempr = LOWER; tempr <= UPPER; tempr += STEP ) System.out.println( "t,C = " + tempr + "\tT,K = " + df.format(tempr + DELTA) ); } } Оператор цикла for содержит в круглых скобках три выражения, разделенных точкой с запятой. В начале идет описание и инициализация переменной цикла tempr, затем проверка условия и приращение переменной цикла. Цикл for работает следующим образом. Вначале происходит инициализация переменной tempr значением LOWER. После этого значение tempr сравнивается с UPPER. Если условие истинно, то выполняется тело цикла. В нашем случае фигурные скобки опущены, т.к. телом цикла является один 17 оператор, в противном случае скобки нужны. Затем осуществляется приращение tempr на STEP, проверка условия. Цикл выполняется в такой последовательности пока условие истинно. Как только условие становится ложным, выполнение цикла прекращается и осуществляется переход к следующему за циклом оператору. Если при первом выполнении цикла условие оказывается ложным, тело цикла не выполняется ни разу, и осуществляется переход к следующему за циклом оператору. Замечание. Иногда оказывается, что условие в цикле истинно всегда. В этом случае компьютер «зависает». Надо избегать таких ситуаций. Задания. Указание: В заданиях 1-4 использовать цикл while, в последующих заданиях использовать цикл for. Дано число a > 1. Вычислить члены бесконечной последовательности 1. a, a2 , a3 , …, меньшие b. Указание: ввести временную переменную, инициализированную значением a, которая при каждом шаге цикла умножается на a. 2. Дано вещественное a, причем 0 a 1. Найти наибольшее число вида 1 2 n , n 0 , меньшее a. 3. Вычислить приближенно значение бесконечной суммы. Указания: а) Условием остановки вычисления может являться то, что разность значений суммы на текущем шаге и на предыдущем равна наперед заданному числу, например 10-5, называемому точностью вычислений. б) При вычислении суммы переменную, в которой будет накапливаться сумма, надо инициализировать нулем. 18 1 3.1. 1 2 2 1 3 2 1 4 2 ... Ответ: 2 6 . 3.2. 1 1 1 1 ... Ответ: 0.6931478. 2 3 4 3.3. 1 x x 2 x3 ... Указания: а) Обратить внимание на то, что 1! 2! 3! xi x i 1 x . б) Сравнить результат с e x . i! i 1! i 4. Вычисление по рекуррентной формуле. Для вычисления квадратного корня из числа u 0 используется следующая последовательность x1 u 1 1 u , i 2,3,4,... , , xi xi 1 2 2 xi 1 u при i . Вычислить члены которой сходятся к 2, 3, 5 . Указания: а) Задать точность вычислений, т.е. величину на которую должны отличаться значения квадрата x на данном шаге и u. б) Последовательность вычислений следующая. Вычисляется x1, затем по известному x1 вычисляется x2 и т.д. Все вычисления осуществляются в цикле. 5. Пусть задано натуральное число n. Вычислить сумму: 5.1. 13 2 3 33 ... n 3 . 5.2. 5.3. 6. 1 1 1 ... . 1 2 n 1 12 1 22 ... 1 n2 . Пусть задано натуральное число n. Вычислить n!. Указание: При вычислении произведения чисел в цикле переменную, в которой будет накапливаться произведение, надо инициализировать единицей. 19 7. n Вложенные циклы. Пусть задано натуральное число n. Вычислить n n 1 1 1 ... . Указание: Каждый член ряда надо вычислять с помощью 1 2 n цикла. Этот цикл помещается внутрь цикла, который суммирует члены ряда. 4 ПРОСТЕЙШИЕ АЛГОРИТМЫ НА ЯЗЫКЕ ЯВА 4.1 РЕШЕНИЕ НЕЛИНЕЙНЫХ УРАВНЕНИЙ Рассмотрим задачу: на воду спущен шар радиуса r, изготовленный из вещества с плотностью, меньшей плотности воды; требуется найти расстояние l от цента шара до поверхности воды (Рисунок 1). Условие равновесия шара Mg = Fa, или шVш g вVпогр g , где объем шара и его погруженной части соответственно равны: 4 3 4h 2 3r h. Vш r , Vпогр 3 3 Подставим это в условие равновесия: 4 3 1 3 ш r 3 в h 2 (3r h) . 20 Рисунок 1 После необходимых сокращений последнее равенство можно преобразовать к кубическому уравнению: h 3rh 3 2 4 ш r 3 в 0. Решив это уравнение можно найти h. Перепишем полученное уравнение в виде: f h h 3rh 3 2 f h 0. 4 ш r 3 в , Решим это уравнение на отрезке h 0,2r . Точка 0 соответствует случаю, когда нижняя точка шара касается поверхности воды, точка 2r – когда верхняя точка касается поверхности воды (т. е. весь шар погружен в воду). Определим значения функции f на границах отрезка. Подставим вместо h ноль и 2r. Видно, что f(0) > 0, а f(2r) < 0. Получается, что на границах отрезка значения функции имеют противоположные знаки. Так как функция непрерывна, то на этом отрезке она хоть раз пересекает ось h, т.е. уравнение имеет хоть один корень (Рисунок 2). 21 Рисунок 2 Для решения уравнения на отрезке [a,b] воспользуемся методом половинного деления. Обозначим значение функции на левой границе отрезка через fa, а на правой через fb. Разобьём отрезок [a,b] пополам и обозначим c ab . 2 Если окажется, что f(a) и f(c) имеют противоположные знаки, дальше будем дробить отрезок [a,c], в противном случае [c,b]. Дробление пополам будем продолжать до тех пор, пока ширина отрезка не станет меньше некоторого наперед заданного числа ε. В этом случае любую из точек полученного отрезка мы можем взять в качестве решения, причем ε это точность с которой получено решение. Прежде чем писать программу для произвольного уравнения, напишем и проверим программу для какого-нибудь простого уравнения, решение которого известно. Например, рассмотрим уравнение f x x 2 2 0 , решением которого 22 является 2 . Ясно, что положительное решение этого уравнения лежит на отрезке [0,2]. Следующий фрагмент программы иллюстрирует этот алгоритм. Пример 9. import java.text.*; public class StepSearch { public static void main( String[] args ) { double fa, fb, xa, xb, xc, fc; DecimalFormat df = new DecimalFormat( "#.00000" ); final double EPS = 1E-5; xa = 0.; xb = 2.; fa = xa*xa - 2.; while( Math.abs( xb - xa ) > EPS ) { xc = ( xb + xa )/2.; fc = xc*xc - 2.; if( fa*fc >= 0) { xa = xc; fa = fc; } else { xb = xc; fb = fc; } } 23 System.out.println( "a = " + df.format( xa ) + ", b = " + df.format( xb ) ); } } Видно, что каждый раз, когда нам требуется вычислить значение функции f(x), приходится выписывать всю формулу. Чтобы избежать этого вводятся так называемые методы, которые представляют собой наборы инструкций и имеют какое-то имя. В нашем случае, для упрощения вычислений удобно ввести метод, который можно назвать fnc, который будет вычислять x2 - 2. static double fnc( double x ) { return x*x - 2.; } Запись double fnc( double x ) означает, что метод с названием fnc, берет вещественное число x и возвращает некоторое вещественное число. В фигурных скобках перечисляются инструкции, с помощью которых исходное число x преобразуется в результат. Ключевое слово return, означающее “вернуть”, показывает, что возвращается функцией. Метод fnc можно использовать в программе следующим образом: fc = fnc( xc );. Такая запись означает: берем число xc, передаем его методу fnc, возвращающему значение, которое записывается в переменную fc. Перепишем нашу программу с использованием метода. Пример 10. import java.text.*; public class StepSearch1 { public static void main( String[] args ) { double fa, fb, xa, xb, xc, fc; 24 DecimalFormat df = new DecimalFormat( "#.00000" ); final double eps = 1E-5; xa = 0.; xb = 2.; fa = fnc( xa ); while( Math.abs( xb - xa ) > eps ) { xc = ( xb + xa )/2.; fc = fnc( xc ); if( fa*fc >= 0) { xa = xc; fa = fc; } else { xb = xc; fb = fc; } } System.out.println( "a = " + df.format( xa ) + ", b = " + df.format( xb ) ); } static double fnc( double x ) { double tmp = x*x; return 2.-tmp; } } 25 Рассмотрим еще один пример метода. Наш метод будет рассчитывать функцию f(h), рассмотренную ранее. Пример 11. static double fnc( double h, double r, double roWater, double roBall ) { double h2 = h*h; return h*h2-3.*r*h2+4.*roBall*r*r*r/roWater; } Мы указали, что тип значения, которое возвращает метод fnc, это double. Методы могут возвращать результаты других типов, например int, или ничего не возвращать, тогда тип возвращаемого значения будет void. Далее, наш метод принимает четыре аргумента типа double. Метод может иметь любое количество аргументов различных типов. При этом аргументы должны передаваться в том порядке, в каком они идут в описании метода. Программа, вычисляющая глубину погружения шарика, будет иметь следующий вид. Пример 12. import java.text.*; public class StepSearch2 { public static void main( String[] args ) { double fa, fb, xa, xb, xc, fc; DecimalFormat df = new DecimalFormat( "#.00000" ); final double eps = 1E-5; double r = 1., roWater = 1., roBall = .8; xa = 0.; xb = 2.*r; fa = fnc( xa, r, roWater, roBall ); 26 while( Math.abs( xb - xa ) > eps ) { xc = ( xb + xa )/2.; fc = fnc( xc, r, roWater, roBall ); if( fa*fc >= 0) { xa = xc; fa = fc; } else { xb = xc; fb = fc; } } System.out.println( "a = " + df.format( xa ) + ", b = " + df.format( xb ) ); } static double fnc( double h, double r, double roWater, double roBall ) { double h2 = h*h; return h*h2-3.*r*h2+4.*roBall*r*r*r/roWater; } } Задания. 1. Написать метод. Указание: Вызвать метод из основной программы и убедиться, что метод возвращает правильное значение. a. Метод, которому передаются длины сторон треугольника и который вычисляет площадь треугольника по формуле Герона. 27 b. Метод, которому передаются коэффициенты квадратного уравнения и который вычисляет дискриминант. c. Даны действительные числа s и t. Найти g(1.2, -s) + g(t ,s) -g(2s-1, st), где g a, b a2 b2 a 2 3ab 3b 2 4 . Указание: Написать метод g. d. Даны действительные числа a, b и c. Найти max a, a b max a, b c . Написать метод max. 1 max a bc,1.15 2. Набрать и запустить программу вычисления 2 . Вычислить алгебраическое значение 3 , 5 , 3 7 . Сравнить с расчетами на калькуляторе. 3. Набрать программу вычисления глубины погружения шара. При указанных в тексте примера 12 значениях параметров h получается равным 1.425718549. 4. Найти корень уравнения с точностью 10-6. a. x 2 cos2 x 1 0 на отрезке [0, /2]. Ответ. x = 1.183207. b. x 3 x 2 x 1 0 на отрезке [-2,1]. Ответ. x = -1.0. c. tgx 5. x 1 0 на отрезке [0, /4]. Ответ. x = 0.706328. 2 Ток эмиссии. Плотность тока насыщения при термоэлектронной эмиссии из горячего катода в электровакуумном приборе изменяется по закону A j0 BT 2 exp , kT где А – энергия активации, А = 4 эВ, коэффициент В = 1.3·105 А/(м·К)2, k – постоянная Больцмана. Найти температуру, при которой плотность тока насыщения j0 =100 мА/мм2. Указание: перевести эВ в Дж, умножив на 1.6·10-19. 28 4.2 ЧИСЛЕННОЕ ИНТЕГРИРОВАНИЕ. Рассмотрим задачу. Шар, радиуса r, плавает на поверхности воды, погруженный в нее на глубину h=αr (α<2). Требуется найти работу, которую надо затратить, чтобы погрузить шар под воду целиком. Напишем программу вычисления работы, зная плотности шарика и воды, а также α и r. Чтобы шар полностью погрузился, его центр должен пройти расстояние 2rαr=(2-α)r. При этом шар надо толкать с силой Vпогр F FA mg g вVпогр шVш g шVш в 1 V ш ш 2 h 3r h 4 g g r 3 ш в 3 1 (3 в rh 2 в h 3 4 ш r 3 ) . 4 3 ш 3 r 3 3 Чтобы полностью погрузить шар, надо совершить работу A 2 r Fdh . r Для вычисления работы воспользуемся численным интегрированием. Рассмотрим произвольную функцию f(x). Пусть надо посчитать площадь под графиком на отрезке [a,b]. Для этого разобьём отрезок на полоски шириной h. Вместо площади под кривой возьмем сумму площадей прямоугольников шириной h и высотой, равной значению функции в середине каждого отрезка. Ясно, что чем меньше h, тем ближе сумма площадей прямоугольников к площади криволинейной трапеции (Рисунок 3). 29 Прежде чем приступать к вычислению работы, посчитаем площадь под кривой f x x 2 на отрезке [-1,2]. Интегрированием можно убедиться, что эта площадь равна 3. Пример 13. public class IntApp { public static void main( String[] args ) { double a, b, h, x, sum; int n = 100; a = -1.; b = 2.; h = (b-a)/(double)n; sum = 0.; x = a + .5*h; for( int i = 0; i < n; i++ ) { sum += fnc( x ); x += h; } sum *= h; System.out.println( "The area = " + sum ); } static double fnc( double x ) { return x*x; } } 30 Рисунок 3 Задания: Написать функцию, вычисляющую силу в зависимости от глубины 1. погружения и вычислить работу. Вычислить работу, необходимую для того, чтобы вытащить шар из 2. воды. 3. Вычислить интегралы: 2 a. 1 b. x 3 0 x 2 1 2 dx cos2 x dx . Ответ: 0.15 . Ответ: 3 x 1 dx . Ответ: 14.6(6) x 4 9 c. 4. Используя численное вычисление интеграла найти приближенное значение π. Для этого вычислить площадь четверти единичного круга 1 1 xdx . Площадь единичного круга равна π. 0 1 5. Приближенно вычислить π с помощью интеграла 0 31 dx 1 x2 4 . 6. Рассмотренный называется ранее алгоритмом алгоритм средних численного прямоугольников, интегрирования т.к. значение подынтегральной функции вычислялось в середине отрезков. Аналогично можно рассмотреть алгоритм левых и правых прямоугольников, когда значение подынтегральной функции вычисляется на левых и правых границах отрезков разбиения. Написать программы вычисления π из задания 4 с помощью методов левых и правых прямоугольников. Сравнить результаты, полученные различными методами. 7. Найти долю молекул азота, имеющих скорости от 700 до 2000 м/с при температуре 20ºС. Как изменится эта доля с ростом температуры. Указание: сделать в интеграле такую замену переменных, чтобы подынтегральное выражение не зависело от констант типа температуры или молярной массы. 32 Приложение А Примитивные типы данных в языке Ява Примитивный Размер Минимальное Максимальное тип значение — значение boolean — — char 16-bit Unicode 0 Unicode 216- 1 byte 8-bit +127 short 16-bit -215 +215—1 int 32-bit -231 +231—1 long 64-bit -263 +263—1 float 32-bit 2-149 (2-2-23)·2127 double 64-bit 2-1074 (2-2-52)·21023 void — -128 — Примечание. В языке Ява размер всех типов одинаков для всех систем. Переменная типа boolean принимает только значения true и false, т.е. истина и ложь. Переменная типа char служит для хранения литер. Применение типа void, или так называемого пустого типа, будет обсуждаться позднее. Все остальные типы используются для хранения числовых данных, причем типы byte, short, int и long используются для хранения целых чисел, а float и double – для хранения дробных. Разные числовые данные имеют разные размеры и разные диапазоны изменения 33 величин. Можно либо сэкономить память, либо получить большую точность, если речь идет о дробных числах. 34 Приложение Б Ключевые слова языка Ява abstract continue for New switch assert default if Package synchronized boolean do goto Private this break double implements Protected throw byte else import Public throws case enum instanceof Return transient catch extends int Short try char final interface Static void class finally long Strictfp volatile const float native Super while 35 Приложение В Математические операторы и операторы сравнения Операторы сравнения, результатом которых является величина типа boolean: o Операторы сравнения чисел <, <=, >, and >= o Операторы равенства чисел == and != Математические операторы результатом которых являются величины типа float или double: o Унарные плюс и минус операторы + и - o Мультипликативные операторы *, /, and % o Аддитивные операторы + и - o Инкрементный оператор ++, и префиксный и постфиксный o Декрементый оператор --, и префиксный и постфиксный 36 Приложение Г Некоторые математические функции и константы (Math.*) static double E основание натурального логарифма static double PI Число Пи. static double abs(double a) Возвращает модуль a. static float abs(float a) static int abs(int a) static long abs(long a) static double acos(double a) Возвращает значение арккосинуса числа, лежащее между 0 и пи. static double asin(double a) Возвращает значение арксинуса числа, лежащее между -pi/2 и pi/2. static double atan(double a) Возвращает значение арксинуса числа, лежащее между -pi/2 и pi/2. static double ceil(double a) Возвращает наименьшее число с плавающей точкой, которое не меньше аргумента и равно математическому целому (округляет до большего). static double cos(double a) Возвращает косинус угла. static double exp(double a) Возвращает ea. static double floor(double a) Возвращает наибольшее число с плавающей точкой, которое не больше аргемента и равно математическому целому (округляет до меньшего). static double log(double a) Возвращает натуральный логарифм числа. 37 static double pow(double a, double b) Возвращает ab. static double random() Возвращает положительное число с плавающей точкой большее или равное 0 и меньшее 1. static double rint(double a) Возвращает число с плавающей точкой, самое близкое к аргументу и равное математическому целому (округляет). static long round(double a) Возвращает наиболее близкое к аргументу длинное целое. static int round(float a) Возвращает наиболее близкое к аргументу целое. static double sin(double a) Возвращает синус угла. static double sqrt(double a) Возвращает правильно округленнй квадратный корень с положительным знаком. static double tan(double a) Возвращает тангенс угла. 38 Список литературы 1 Льюис Д. Java 2 / Льюис Д., Мюллер П. – М.: НТ Пресс, 2005. – 288 с. – ISBN 5-477-00049-X. 2 Ноутон П. Java 2 / Ноутон П., Шилдт Г. – СПб.: БХВ – Петербург, 2001. – 1072 с. – ISBN 5-94157-012-0. 3 Абрамов С.А. Начала информатики / Абрамов С.А., Зима Е.В. – М.: Наука, 1989. – 256 с. – ISBN 5-02-013958-0. 4 Гулд Х. Компьютерное моделирование в физике. Часть 1 / Гулд Х., Тобочник Я. М.: Мир, 1990. – 350 с. 5 Бурсиан Э.В. Физика. 100 задач для решения на компьютере / Бурсиан Э.В. – СПб.: ИД «МиМ», 1997. – 256 с. – ISBN 5-7562-0107-6. 39