Особые ситуации в арифметических выражениях

Однако и при допустимых преобразованиях существуют особые ситуации, которые необходимо предусматривать. Например, если присваивать переменной вещественного типа целое значение с очень большим количеством значащих цифр, то младшие разряды числа могут быть потеряны.

Пример:

float х = 12345678987654321L; // справа long

Переменная х получает значение 1.234568Е+16 — потеряны младшие разряды.

При делении вещественных чисел существует опасность переполнения, если порядок делимого существенно больше порядка делителя. В этом случае результат, независимо от конкретных величин мантисс делимого и делителя, воспринимается исполняющей системой как бесконечность (Infinity). Такое же значение получается при делении на нулевое значение.

Переполнение возможно и при других арифметических операциях. Например, в результате выполнения следующего фрагмента программы: float x = 1E+24F;

Console.Write("x = " + (x *= x)); на консольный экран будет выведена строка: х = бесконечность

Обратная переполнению ситуация — потеря значимости возникает, когда получаемое значение слишком мало и не может быть представлено с помощью того количества разрядов (битов), которые выделяются для значения соответствующего типа. В качестве примера рассмотрим следующий фрагмент программы:

float х = 1E-24F;

Console.Write("x = " + (х *= х));

Результат в этом случае нулевой: х = 0

В случае, когда и делитель, и делимое равны нулю, результат неопределенный, и это фиксируется с помощью специального обозначения NaN (Not a Number — не число). При выполнении следующих операторов:

float х = 0.0f;

Console.Write("0/0 = " + x/0);

Результат в консольном экране будет таким:

0/0 = NaN

При решении вычислительных задач с помощью итерационных алгоритмов возникает задача оценки необходимого количества итераций. Например, если алгоритм приведен к виду

fi+i=fi+', i = 1,2,...

и Д, по какому-либо закону убывает с ростом i, то предельная точность достигается в том случае, когда Д, становится пренебрежительно малой величиной по сравнению с В этом случае говорят, что достигнут машинный нуль относительно величины /г.

Рассмотрим такую последовательность операторов:

double х = 1000, у = 1Е-08;

Console.Write("x + у =" + (х + (у *= у)));

Console.Write(" у= " + у);

Результат выполнения:

х + у = 1000 у = 1Е-16

В данном примере прибавление значения 1Е-16 к 1000 не изменило результата, и 1Е-16 является машинным нулем относительно величины 1000. При необходимости можно ставить и решать задачу оценки максимального по абсолютной величине значения машинного нуля относительно заданной величины.

Если переменной типа decimal необходимо присвоить значение, отличное от целого, то его нужно представить в виде константы типа decimal. Целое значение можно присваивать десятичной переменной непосредственно. Следующий фрагмент программы (04_01.cs) иллюстрирует некоторые особенности выражений с операндом типа decimal. (Напомним, что десятичный литерал имеет суффикс m или М.)

static void Main()

{

decimal p = 193, d = 0.15431m, e = 1.231E-10M;

Console.WriteLine("p*d*e= " + (p * d * e));

float bp = 193F, bd = 0.15431F, be = 1.231E-10F;

Console.WriteLine("bp*bd*be= " + (bp * bd * be));

Console.WriteLine("l.0/3.0= " + (1.0 / 3.0));

Console.WriteLine("1.0m/3.0m= " + (1.0m / 3.0m));

}

Переменным p, d, e типа decimal и переменным bp, bd, be типа float присвоены одинаковые значения. Результаты одинаковых выражений с операндами разных типов существенно различны по точности;

p*d*e= 0,000000003666143273

bp*bd*be= 3,666143Е-09

  • 1.0/3.0= 0,333333333333333
  • 1.0m/3.0m= 0,3333333333333333333333333333
 
Посмотреть оригинал
< Пред   СОДЕРЖАНИЕ   ОРИГИНАЛ     След >