ПОНЯТНО О Visual Basic NET

Single и Double – десятичные дроби


С типом дробных чисел Double мы встретились в 5.2.3. Познакомимся поближе с ним и с типом Single. Оба они предназначены для работы с целыми и дробными числами и различаются, согласно таблице, точностью и диапазоном значений.

Создайте кнопку и введите такую программу:

Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button3.Click

        Dim a, b, c As Single

        a = 23.456

        b = 100

        c = a + b

        WriteLine(a) : WriteLine(b) : WriteLine(c)

        Dim d, f, g As Double

        d = 123456789

        f = 0.000555

        g = d + f

        WriteLine(d) : WriteLine(f) : WriteLine(g)



End Sub

Обратите внимание, что оператор Dim d, f, g As Double находится не на самом верху процедуры. Это ничего. Надо только, чтобы объявление переменной было расположено в процедуре раньше ее «употребления».

Запустите проект. Вот результат:

23,456

100

123,456

123456789

0,000555

123456789,000555

Все правильно. Попробуем теперь проверить тип Single на прочность, как мы проверяли тип Integer. Попробуем записать вместо  a = 23.456 очень длинную дробь:

a = 23.45678901234567890123456789

Но VB не дает нам роскошествовать. Он прямо в окне кода укорачивает строку до:

        a = 23.456789012345681

причем даже чуть-чуть искажает число. Поставим курсор мыши на этот литерал и увидим подсказку «Double». Почему? Ведь переменная a имеет тип Single! Дело в том, что VB, пока проект не запущен, не утруждает себя угадыванием смысла литералов в окне кода и все дробные литералы «стрижет под Double». Запустим проект. Вот первые три числа результатов:

23,45679

100

123,4568

Как видите, VB обрезал наши длинные числа до 7 значащих цифр. Сделал он это потому, что 4 байта, отведенные под ячейку памяти для переменной типа Single, не в состоянии вместить больше. Если мы хотим иметь большую точность, то объявляем наши переменные типом Double. Под переменную типа Double компьютер отводит в памяти 8 байтов и поэтому она может быть гораздо длиннее – 17 значащих цифр.


Попробуем задать очень маленькое число. Вместо f = 0.000555 напишем:

        f = 0.0000000000000000000000000000000000000000000000000000000000000543

Но VB не любит в дробных числах большого числа нулей и вот, хоть запись и правильная и вполне по зубам типу Double, VB прямо в окне кода укорачивает строку до:

        f = 5.43E-62

Это тоже правильная запись, а что она значит, объяснено чуть позже, в 5.4.7.

Поговорим о точности вычислений. Если вы до сих пор считаете, что компьютер все вычисления выполняет абсолютно точно, то ошибаетесь. Компьютер всего лишь очень точен. Очень, а не абсолютно. И в этом вы скоро убедитесь. Начнем хотя бы с того, что VB не умеет работать с обыкновенными дробями. Он не знает, что такое 1/3, поэтому нам приходится задавать компьютеру вместо числа 1/3 число 0,333333333333. Но это ведь не точная дробь 1/3, а только приблизительное значение. Чтобы она стала точным значением, число знаков после запятой должно быть бесконечным, а такое число не уместится в памяти компьютера. Следовательно, даже теоретически компьютер не может быть абсолютно точен.

Во-вторых, из-за ограниченности типа Double 17 значащими цифрами операции даже над очень точными числами выполняются не совсем точно. Что, например, напечатает такой фрагмент?:

        Dim d, f, g As Double

        d = 123456789

        f = 0.00987654321098765

        g = d + f

        WriteLine(d) : WriteLine(f) : WriteLine(g)

Если вы думаете, что точную сумму 123456789,00987654321098765, то ошибаетесь, так как такое длинное число не уместится в типе Double. А напечатано будет вот что:

123456789

0,00987654321098765

123456789,009877

Десяток цифр из точного значения суммы обрезаны.

Целые литералы VB автоматически относит к типу Integer, а если они слишком длинные для Integer – к типу Long. Дробные литералы VB относит к типу Double. Все это он делает, не особенно обращая внимание на то, что переменные в том же операторе имеют другой тип.


Содержание раздела