
ЯП Лабораторная работа 2
.pdfМинистерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования
ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР)
Кафедра комплексной информационной безопасности электронновычислительных систем (КИБЭВС)
ВЕЩЕСТВЕННЫЕ ЧИСЛА. ОШИБКИ ПРИ РАБОТЕ С ВЕЩЕСТВЕННЫМИ ЧИСЛАМИ
Отчет по лабораторной работе №2 по дисциплине «Языки программирования»
Вариант №4
Студент гр. 7х3-х
_______ ххххххххх
_______
Приняла: Преподаватель каф. КИБЭВС
_______ хххххххх
_______
Томск 2025
Введение
Целью работы является знакомство с основными ошибками, возникающими при обработке вещественных чисел.
Постановка задачи:
1.Изучить теоретические сведения;
2.В качестве исходных значений принять следующие значения:
x=<номер студенческого билета><номер группы>,<дата рождения ддммгггг>;
y=x*10-10; c=x+y;
c’= округление с до 9 знака после запятой; z=x±10-8;
k=округл.до целого(х);
3.Произвести вычисления, и показать каким образом возникают ошибки при работе с вещественными числами. Все значения вычислять с максимальной точностью, не округляя. Относительную ошибку вычислять с точность до 10 значащих цифр;
4.Объяснить полученные результаты;
5.Для выбранного варианта задания изучить, какие типы данных есть в языке программирования, как они реализованы;
6.Написать программы, демонстрирующие ошибки вещественных чисел на языке программирования, соответствующего варианту;
7.Написать отчет и защитить у преподавателя.
2
1 РУЧНОЕ ВЫЧИСЛЕНИЕ
Согласно варианту задания были получены следующие значения чисел:
1.х = 93710247132,31052005
2.y = x * 10-10 = 9,371024713231052005
3.c = x + y = 93710247141,681544763231052005
4.c’ = 93710247141,681544763
5.Абсолютная ошибка: A = |c – c’| = 0,000000000231052005
6.Относительная ошибка: O = A/c = 2,4656002096619161992663764192758e21
7.z1 = x – 10-8 = 93710247132,31052004
8.z2 = x + 10-8 = 93710247132,31052006
9.m = x * x = 8781610417598712046673,9784159015
10.n1 = x * z1 = 8781610417598712045736,8759445783
11.n2 = x * z2 = 8781610417598712047611,0808872246
12.Абсолютная ошибка с учетом ошибки z1 в разряде: A1 = |m – n1| = 937,1024713232
13.Абсолютная ошибка с учетом ошибки z2 в разряде: A2 = |m – n2| = 937,1024713231
14.Относительная ошибка с учетом ошибки z1 в разряде: О1 = А1/m = 1,0671191578314698659182968027373e-19
15.Относительная ошибка с учетом ошибки z2 в разряде: О2 = А2/m = 1,0671191578313559915885957312274e-19
16.k = 93710247132
17.Абсолютная ошибка при округлении числа до целой части: А = |х – k| = 0,31052005
18.Относительная ошибка при округлении числа до целой части: О = А/х = 3,3136189424575239298634436829992e-12
3

2 ПОДСЧЕТ С ПОМОЩЬЮ ПРОГРАММЫ
Для выполнения работы был выбран язык программирования Java, исходный код программы представлен в приложении А.
На рисунке 2.1 – рисунке 2.3 представлены вычисленные результаты при использовании типов float, double и встроенного класса BigDecimal.
Рисунок 2.1 – Результат работы программы с использованием типа float
Рисунок 2.2 – Результат работы программы с использованием типа double
4

Рисунок 2.3 – Результат работы программы с использованием встроенного класса BigDecimal
Так как диапазон значений BigDecimal ограничен лишь памятью виртуальной машины (т.е. теоретически неограничен), расчеты произведенные с использованием этого класса больше всего соответствуют расчетам, произведенным вручную.
При использовании типов float и double возникают ошибки исчезновения операнда (рисунок 2.4), умножения ошибки (рисунок 2.5) и потери значимости (рисунок 2.6).
Рисунок 2.4 – Исчезновение операнда в типах float и double
Рисунок 2.5 – Умножение ошибки типов float и double
5

Рисунок 2.6 – Потеря значимости типов float и double
6
Заключение
В ходе выполнения данной работы были получены знания об основных ошибках, возникающих при обработке вещественных чисел.
7
Приложение А Код программы
import java.math.BigDecimal; import java.math.RoundingMode;
public class Main |
{ |
public static |
void Float(){ |
float x = |
Float.parseFloat("93710247132.31052005"); |
float y = |
x * Float.parseFloat(String.valueOf(Math.pow(10, -10))); |
float c = |
x + y; |
|
float c_approx = (float)((BigDecimal.valueOf(c)).setScale(9, |
RoundingMode.HALF_UP)).doubleValue();
float Ac = Math.abs(c - c_approx); float Oc = Ac/c;
float z_plus = x + Float.parseFloat(String.valueOf(Math.pow(10, -8))); float z_minus = x - Float.parseFloat(String.valueOf(Math.pow(10, -8)));
float Az_plus = Math.abs((x*x) - (x*z_plus)); float Oz_plus = Az_plus/(x*x);
float Az_minus = Math.abs((x*x) - (x*z_minus)); float Oz_minus = Az_minus/(x*x);
float k = Math.round(x);
float Ak = Math.abs(x - k); float Ok = Ak/x;
System.out.printf("Расчет входных данных: \n x = %.10f \n y = %.10f \n c = %.10f \n c' = %.10f", x, y, c, c_approx);
System.out.printf("\n\nАбсолютная ошибка: A = %.10f \nОтносительная ошибка: O = %.10f", Ac, Oc);
System.out.printf("\n\nЗначение Z: \n x + 10^(-8) = %.10f \n x - 10^(-8) = %.10f", z_plus, z_minus);
System.out.printf("\n\nАбсолютная ошибка: A1 = %.10f ; A2 = %.10f \ nОтносительная ошибка: O1 = %.10f ; O2 = %.10f", Az_plus, Az_minus, Oz_plus, Oz_minus);
System.out.printf("\n\nОкругление Х до целого: \n k = %.0f", k);
8
System.out.printf("\n\nАбсолютная ошибка: A = %.10f \nОтносительная ошибка: O = %.10f", Ak, Ok);
}
public static void Double(){
double x = Double.parseDouble("93710247132.31052005");
double y = x * Double.parseDouble(String.valueOf(Math.pow(10, -10)));
double c = x + y;
double c_approx = ((BigDecimal.valueOf(c)).setScale(9, RoundingMode.HALF_UP)).doubleValue();
double Ac = Math.abs(c - c_approx); double Oc = Ac/c;
double z_plus = x + Double.parseDouble(String.valueOf(Math.pow(10, -8))); double z_minus = x - Double.parseDouble(String.valueOf(Math.pow(10, -8)));
double Az_plus = Math.abs((x*x) - (x*z_plus)); double Oz_plus = Az_plus/(x*x);
double Az_minus = Math.abs((x*x) - (x*z_minus)); double Oz_minus = Az_minus/(x*x);
double k = Math.round(x);
double Ak = Math.abs(x - k); double Ok = Ak/x;
System.out.printf("Расчет входных данных: \n x = %.10f \n y = %.10f \n c = %.10f \n c' = %.10f", x, y, c, c_approx);
System.out.printf("\n\nАбсолютная ошибка: A = %.10f \nОтносительная ошибка: O = %.10f", Ac, Oc);
System.out.printf("\n\nЗначение Z: \n x + 10^(-8) = %.10f \n x - 10^(-8) = %.10f", z_plus, z_minus);
System.out.printf("\n\nАбсолютная ошибка: A1 = %.10f ; A2 = %.10f \ nОтносительная ошибка: O1 = %.10f ; O2 = %.10f", Az_plus, Az_minus, Oz_plus, Oz_minus);
System.out.printf("\n\nОкругление Х до целого: \n k = %.0f", k); System.out.printf("\n\nАбсолютная ошибка: A = %.10f \nОтносительная ошибка: O
= %.10f", Ak, Ok);
}
public static void BigDecimal(){
BigDecimal x = new BigDecimal("93710247132.31052005");
9
BigDecimal y = x.multiply(BigDecimal.valueOf(Math.pow(10, -10)));
BigDecimal c = x.add(y);
BigDecimal c_approx = c.setScale(9, RoundingMode.HALF_UP);
BigDecimal Ac = c.subtract(c_approx);
if (Ac.compareTo(new BigDecimal("0")) == -1){ Ac = Ac.multiply(BigDecimal.valueOf(-1));
}
BigDecimal Oc = Ac.divide(c, 10, RoundingMode.HALF_UP);
BigDecimal z_plus = x.add(BigDecimal.valueOf(Math.pow(10, -8))); BigDecimal z_minus = x.subtract(BigDecimal.valueOf(Math.pow(10, -8)));
BigDecimal Az_plus = (x.multiply(x)).subtract(x.multiply(z_plus)); if (Az_plus.compareTo(new BigDecimal("0")) == -1){
Az_plus = Az_plus.multiply(BigDecimal.valueOf(-1));
}
BigDecimal Oz_plus = Az_plus.divide((x.multiply(x)), 10,
RoundingMode.HALF_UP);
BigDecimal Az_minus = (x.multiply(x)).subtract(x.multiply(z_minus)); if (Az_minus.compareTo(new BigDecimal("0")) == -1){
Az_minus = Az_minus.multiply(BigDecimal.valueOf(-1));
}
BigDecimal Oz_minus = Az_minus.divide(x.multiply(x), 10,
RoundingMode.HALF_UP);
BigDecimal k = x.setScale(0,RoundingMode.HALF_UP);
BigDecimal Ak = x.subtract(k);
if (Ak.compareTo(new BigDecimal("0")) == -1){ Ak = Ak.multiply(BigDecimal.valueOf(-1));
}
BigDecimal Ok = Ak.divide(x, 10, RoundingMode.HALF_UP);
System.out.printf("Расчет входных данных: \n x = %.10f \n y = %.10f \n c = %.10f \n c' = %.10f", x, y, c, c_approx);
System.out.printf("\n\nАбсолютная ошибка: A = %.10f \nОтносительная ошибка: O = %.10f", Ac, Oc);
System.out.printf("\n\nЗначение Z: \n x + 10^(-8) = %.10f \n x - 10^(-8) = %.10f", z_plus, z_minus);
10