- •Лабораторная работа 1 Язык Go. Введение. Объявление констант и переменных. Логические значения и числовые типы данных
- •Задание 1.1 Выведем на экран строку «Моя first программа на Go».
- •Задание 1.2 Написать программу, которая выводит сообщение вида «Иван изучает язык Go» (имя и название языка это аргументы командной строки, переданные программе при выполнении).
- •Задание 1.3 Нужно вывести сообщения вида «ИмяN изучает языкN». Пусть в командной строке задается 2n атрибутов в формате «имя файла имя1 язык1 имя2 язык2 ...»
- •Задание 1.4 Реализуйте вышеописанный пример, используйте различные варианты присваивания значений переменной X (латинские и русские символы).
- •Задание 1.8 Выполните проверку этого задания.
Задание 1.8 Выполните проверку этого задания.
Рассмотрим пример использования битовых операций для интерпретации значения uint8 в качестве набора восьми независимых битов. Он использует символы преобразования %b в Printf для вывода двоичных цифр числа; 08 уточняет поведение %b, заставляя дополнять результат нулями так, чтобы выводилось ровно 8 цифр.
var х uint8 = 1<<1 | 1<<5
var у uint8 = 1<<1 | 1<<2
fmt.Printf("%08b\n", х)// "00100010", множество {1,5}
fmt.Printf("%08b\n", у) // "00000110", множество {1,2}
fmt.Printf("%08b\n", x&y) //"00000010", пересечение {1}
fmt.Printf("%08b\n", x|у) //"00100110", объединение {1,2,5}
fmt.Printf("%08b\n", x^y) //"00100100", симметричная разность {2,5}
fmt.Printf("%08b\n", x&^y) // "00100000", разность {5}
for i := uint(0); i < 8; i++ {
if x&(l<<i) != 0 { // Проверка принадлежности множеству
fmt.Println(i) // "1", "5"
}
}
fmt.Printf("%08b\n", x<<1) // "01000100", множество {2,6}
fmt.Printf("%08b\n", x>>1) //"00010001", множество {0,4}
Задание 1.9 Выполните проверку рассмотренного примера.
Целочисленные литералы любого размера и типа могут быть записаны как десятичные числа, как восьмеричные числа, если они начинаются с 0 (как 0666), или как шестнадцатеричные, если они начинаются с 0х или 0Х (как 0xabc). Шестнадцатеричные цифры могут быть как прописными, так и строчными. При выводе чисел с использованием пакета fmt можно управлять системой счисления и форматом вывода с помощью символов преобразования %d, %о и %х, как показано в следующем примере:
о := 0666
fmt.Printf("%d %[1]о %#[1]о\n", о) // "438 666 0666"
х := int64(0xabc)
fmt.Printf("%d %[l]x %#[l]x %#[1]Х\n", x) // “2748 abc 0xabc 0XABC”
Обычно форматная строка Printf содержит несколько символов преобразования %, которые требуют того же количества дополнительных аргументов, но [1] после % говорит функции Printf о том, что ей следует использовать первый операнд снова и снова. Во-вторых, наличие # при символах преобразования %о, %х или %Х говорит функции Printf о том, что при выводе должен быть добавлен префикс, указывающий систему счисления 0, 0х или 0Х соответственно.
Задание 1.10 Выполните проверку рассмотренного примера.
Задание 1.11 Выведите таблицу, представленную на рисунке 1.9. Даны два целых числа (первое больше второго), необходимо выполнить арифметические операции над числами и перевести результаты в двоичную, восьмеричную и шестнадцатеричную системы счисления: для ввода чисел воспользуйтесь функцией fmt.Scanf(“%d%d”,&a,&b). Числа вводите через пробел.
Рисунок 1.9 Результат работы приложения
Литералы записываются как символ в одинарных кавычках. Простейший пример с использованием ASCII-символа 'а', но так можно записать любой символ Unicode либо непосредственно, либо с помощью числовых управляющих последовательностей (начинаются с символа \).
Руны выводятся с помощью символов преобразования %с, или %q если требуются апострофы. Например:
ascii := 'а'
Unicode := '★'
newline := '\n'
fmt.Printf("%d %[1]c %[1]q\n", ascii) // "97 a 'a'"
fmt .Printf ("%d %[1]c %[1]q\n", Unicode) // "9733 ★'★'”
fmt.Printf("%d %[1]q\n", newline) // "10 '\n'''
Задание 1.12 Выполните проверку рассмотренного примера. Рассмотрите вывод других символов Unicode.
Рассмотрим вещественные типы данных в Go. Язык предоставляет два варианта чисел с плавающей точкой разного размера, float32 и float64. Их арифметические свойства регулируются стандартом IEEE 754 и реализованы на всех современные процессорах. Рассмотрим диапазоны значений этих типов (таблица 1.6).
Таблица 1.6 Вещественные типы в языке Go
Тип |
Диапазон |
float32 |
±3,402823466385288598117041834
845169254 40
|
float64 |
±1,797693134 862315708145274 237317043567981 10308 Мантисса может быть представлена с точностью до 15 десятичных разрядов |
В языке Go поддерживаются все операции с вещественными числами, перечисленные в таблице 1.3. Большинство констант из пакета math, и все его функции перечислены в таблицах 1.7 и 1.8. Все функции из пакета math принимают и возвращают значения типа float64, если явно не указано иное.
Таблица 1.7 Константы из пакета math
Константа |
Описание |
math.E |
Константа e; примерно 2.718281828459045 |
math.Ln2 |
loge2, примерно 0,693147180559945 |
math.Ln10 |
log102, примерно 2,302585092994045 |
math.Log2E |
|
math.Log10E |
|
math.Pi |
Константа
|
math.Phi |
Константа
|
math.Sqrt2 |
|
math.SqrtE |
|
math.SqrtPi |
|
math.SqrtPhi |
|
Таблица 1.8 Некоторые функции из пакета math
Функция |
Описание |
math.Abs(x) |
|x|, абсолютное значение x |
math.Cbrt(x) |
|
math.Ceil(x) |
math.Ceil(5.4) = = 6.0 |
math.Cos(x) |
Косинус угла x, выраженного в радианах |
math.Exp(x) |
ex |
math.Exp2(x) |
2x |
math.Floor(x) |
math.Floor(5.4) = = 5.0 |
math.Log(x) |
logex |
math.Log10(x) |
log10x |
math.Log2(x) |
log2x |
math.Max(x, y) |
Наибольшее из чисел x и y |
math.Min(x, y) |
Наименьшее из чисел x и y |
math.Mod(x, y) |
Остаток от деления x на y |
math.Pow(x, y) |
xy |
math.Pow10(n) |
10n в виде значения типа float64, где значение n имеет тип int |
math.Signbit(x) |
Возвращает значение типа bool; true, если x является отрицательным числом (включая -0.0) |
math.Sin(x) |
Синус угла x, выраженного в радианах |
math.SinCos(x) |
Синус и косинус угла x, выраженного в радианах |
math.Sqrt(x) |
|
math.Tan(x) |
Тангенс угла x, выраженного в радианах |
math.Trunc(x) |
x с усеченной дробной частью |
Вещественные числа записываются в форме с десятичной точкой или в экспоненциальной форме , например 0.0, 3., 8.2, –7.4, –6e4, .1, 5.9E–3.
С вещественными числами могут использоваться все операторы сравнения, перечисленные в таблице 1.2. Рассмотрим пример:
x, y := 0.0, 0.0
for i := 0; i < 10; i++ {
x += 0.1
if i%2 == 0 {
y += 0.2
} else {
fmt.Printf("%-5t %-5t %-5t %-5t", x == y,
EqualFloat(x, y, -1), EqualFloat(x, y, 0.000000000001),
EqualFloatPrec(x, y, 6))
fmt.Println(x, y)
}
}
Результат работы этой программы представлен на рисунке 1.10.
Рисунок 1.10 Результат работы программы
Здесь сначала создаются две переменные типа float64 с начальными значениями, равными 0. Затем к первой из них десять раз добавляется значение 0.1, ко второй – пять раз значение 0.2, то есть в результате обе переменные должны получить значение 1. Однако, как следует из вывода, представленного ниже, для некоторых вещественных значений невозможно достичь полной точности представления. Ввиду этого необходимо проявлять особую осторожность при сравнении вещественных чисел между собой с помощью операторов == и != . Однако бывают ситуации, когда сравнение вещественных чисел на равенство или неравенство с помощью встроенных операторов имеет особый смысл, например чтобы избежать деления на нуль : if y != 0.0 { return x / y }.
Спецификатор формата "%-5t" выводит логическое значение с выравниванием по левому краю в поле шириной пять символов.
func EqualFloat(x, y, limit float64) bool {
if limit <= 0.0 {
limit = math.SmallestNonzeroFloat64
}
return math.Abs(x-y) <=
(limit * math.Min(math.Abs(x), math.Abs(y)))
}
Функция EqualFloat() сравнивает два значения типа float64 с заданной точностью или с самой большой аппаратной точностью, которой можно достичь, если в аргументе limit было передано отрицательное число (например, –1). Она опирается на использование функций (и констант) из пакета math, входящего в состав стандартной библиотеки.
Можно также использовать другой (более медленный) способ сравнения чисел в виде строк.
func EqualFloatPrec(x, y float64, decimals int) bool {
a := fmt.Sprintf("%.*f", decimals, x)
b := fmt.Sprintf("%.*f", decimals, y)
return len(a) == len(b) && a == b
}
Точность для этой функции определяется количеством знаков после десятичной точки. В спецификаторе формата %, в функции fmt.Sprintf() , можно использовать шаблонный символ *, на место которого будет подставляться число, то есть в данном примере создаются две строки для заданных значений типа float64, для каждого из которых указывается определенное число десятичных знаков. Если числа будут существенно отличаться по величине, соответственно, будут отличаться и длины строк a и b (например, 12.32 и 592.85), поэтому сравнение таких чисел будет выполняться быстрее.
Задание 1.13 Выполните проверку рассмотренного примера.
В большинстве случаев, где необходимы вещественные числа, лучше использовать значения типа float64 , особенно если учесть, что все функции в пакете math оперируют значениями типа float64.
Однако в языке Go имеется также тип float32, который может пригодиться, когда на первое место выходит проблема экономии памяти и не требуется применение функций из пакета math или когда неудобство преобразования значений в тип float64 и обратно не кажется таким значительным. Поскольку в языке Go вещественные числа имеют строго определенный размер, их всегда можно без опаски читать из внешних источников, таких как файлы и сетевые соединения, или записывать в них.
Вещественные числа можно преобразовывать в целые значения, используя стандартный синтаксис (например, int(вещественное_число)), в этом случае дробная часть просто отбрасывается. Разумеется, если вещественное число превосходит по величине максимально возможное значение целочисленного типа, в который выполняется преобразование, в результате будет получено непредсказуемое значение. Решить эту проблему можно с помощью собственной функции преобразования, например:
func IntFromFloat64(x float64) int {
if math.MinInt32 <= x && x <= math.MaxInt32 {
whole, fraction := math.Modf(x)
if fraction >= 0.5 {
whole++
}
return int(whole)
}
panic(fmt.Sprintf("%g выходит за пределы диапазона int32", x))
}
Функция math.Modf() в этом примере используется для выделения дробной и целой частей числа (обе имеют тип float64), но, вместо того чтобы просто вернуть целую часть (то есть выполнить усечение), функция в примере выше округляет целую часть в большую сторону, если дробная часть больше или равна 0.5.
Вместо того чтобы просто вернуть ошибку, как это делает функция Uint8FromInt(), в этой функции выход значения за допустимый диапазон считается веской причиной, чтобы прервать выполнение программы. Поэтому здесь была использована встроенная функция panic() , вызывающая аварию во время выполнения и останавливающая выполнение программы, если аварийная ситуация не будет обработана вызовом функции recover(). То есть, если программа была выполнена успешно, можно быть уверенными, что она не пыталась преобразовать значение, выходящее за допустимый диапазон. Обратите также внимание на отсутствие инструкции return в конце функции – компилятор Go понимает, что в случае вызова функции panic() невозможно нормальное завершение функции в этой точке.
Задание 1.14 Выполните проверку рассмотренного примера.
Задание 1.15 Выполните задания по вариантам (номер варианта совпадает с порядковым номером студента в списке группы).
В первой задаче нужно вывести значение функции при введенных значениях a, b, c, d, x (ввод значений в командной строке).
Вариант 1
Задача 1 f(x) = ax3 + bx2 + cx + d
Задача 2 Даны два числа. Найти среднее арифметическое их квадратов и среднее арифметическое их модулей.
Вариант 2
Задача
1
Задача 2 Скорость лодки в стоячей воде V км/ч, скорость течения реки U км/ч (U < V). Время движения лодки по озеру T1 ч, а по реке (против течения) — T2 ч. Определить путь S, пройденный лодкой.
Вариант 3
Задача 1 f(x)=ab ec + dx
Задача 2 Скорость первого автомобиля V1 км/ч, а второго ‑ V2 км/ч, расстояние между ними S км. Определить расстояние между ними через T часов, если автомобили удаляются друг от друга.
Вариант 4
Задача 1 f(x) = a sin(bx + c) - d
Задача 2 Скорость первого автомобиля V1 км/ч, а второго ‑ V2 км/ч, расстояние между ними S км. Определить расстояние между ними через T часов, если автомобили первоначально движутся навстречу друг другу.
Вариант 5
Задача 1 f(x) = cos(bx - c) + 10d/a
Задача 2 Найти периметр и площадь прямоугольного треугольника, если даны длины катетов a и b.
Вариант 6
Задача 1 f(x) = ln(bx+c) - a/10d
Задача 2 Дана длина ребра куба. Найти площадь грани, площадь полной поверхности и объем куба.
Вариант 7
Задача
1
Задача 2 Найти длину окружности и площадь круга заданного радиуса R.
Вариант 8
Задача
1
Задача 2 Найти площадь кольца, внутренний радиус которого равен R1, а внешний радиус равен R2 (R1 < R2).
Вариант 9
Задача
1
Задача 2 Дана сторона равностороннего треугольника. Найти площадь этого треугольника и радиусы вписанной и описанной окружностей.
Вариант 10
Задача 1 f(x) = a sin x + b cos x + c
Задача 2 Дана длина окружности. Найти площадь круга, ограниченного этой окружностью.
Вариант 11
Задача
1
Задача 2 Дана площадь круга. Найти длину окружности, ограничивающей этот круг.
Вариант 12
Задача
1
Задача 2 Найти периметр и площадь равнобедренной трапеции с основаниями a и b (a > b) и углом α при большем основании (угол дан в радианах).
Вариант 13
Задача 1 f(x) = abx - 2c + d
Задача 2 Найти периметр и площадь прямоугольной трапеции с основаниями a и b (a > b) и острым углом α (угол дан в радианах).
Вариант 14
Задача
1
Задача 2 Найти расстояние между двумя точками с заданными координатами (x1, y1) и (x2, y2).
Вариант 15
Задача
1
Задача 2 Даны координаты трех вершин треугольника (x1, y1), (x2, y2), (x3, y3). Найти его периметр и площадь.
Вариант 16
Задача
1 f(x) = sin(ax
+ 2b
- 10c)
+
Задача 2 Найти корни квадратного уравнения Ax2 + B·x + C = 0, заданного своими коэффициентами A, B, C (коэффициент A не равен 0).
