Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

ЯП Лабораторная работа 2

.pdf
Скачиваний:
0
Добавлен:
17.06.2025
Размер:
527.96 Кб
Скачать

Министерство науки и высшего образования Российской Федерации Федеральное государственное автономное образовательное учреждение высшего образования

ТОМСКИЙ ГОСУДАРСТВЕННЫЙ УНИВЕРСИТЕТ СИСТЕМ УПРАВЛЕНИЯ И РАДИОЭЛЕКТРОНИКИ (ТУСУР)

Кафедра комплексной информационной безопасности электронновычислительных систем (КИБЭВС)

ВЕЩЕСТВЕННЫЕ ЧИСЛА. ОШИБКИ ПРИ РАБОТЕ С ВЕЩЕСТВЕННЫМИ ЧИСЛАМИ

Отчет по лабораторной работе №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