О приведении к целым числам и округлении
Автор: Путевской Виктор
У многих проггеров на VB часто возникают проблемы с правильным преобразованием вещественных чисел или же строк, содержащих числа к целым числам. Проблемы возникают из-за некоторых нюансов использования функций преобразования типов в VB. Рассмотрим же эти функции.
Функции Int и Fix
Эти функции возвращают целую часть числа. Предполагается, что аргументом имеет тип Double или является числовым выражением. Возвращается при Double. А уже этот Double затем можно преобразовать в Integer, Long или же в Byte. Главное, чтобы число уместилось в диапазон нужного вам типа. Разность при использовании Int и Fix заметна только лишь при отрицательном значении аргумента. Дело в том, что Int всегда возвращает ближайшее меньшее целое число, а Fix просто отбрасывает дробную часть. То есть для числа 4.5 и Int и Fix вернут 4, тогда как для числа -4.5, Int вернет -5, а Fix - -4.
Функции CLng и CInt
Эти функции преобразовывают числовые аргументы в целое число типа Long и Integer соответственно. Дробная часть при этом округляется. Таким образом, если исходное число будет равно 1.5, то результатом преобразования при помощи CInt или CLng будет целое число 2. А если аргументом будет 1.4, то в результате получим 1. Знак числа при этом роли не играет, то есть -1.5 будет преобразована в -2, а -1.4 – в -1. Естественно при использовании CLng и CInt надо помнить о диапазонах допустимых значений для типов Long и Integer. Число получаемое после преобразования должно умещаться в эти диапазоны. Например, число 32767.5 после преобразования функцией CInt должно быть равно 32768, что на единицу больше верхней границы представления для типа Integer, тогда как 32767.4 будет преобразовано в 32767 и вполне успешно может быть представлено типом Integer. При преобразовании из строки, содержащей число важно помнить, что функции преобразования используют национальные настройки для получения символа разделения целой и дробной частей числа. Поэтому, если у вас разделителем целой и дробной частей числа является точка «.», а в строковом представлении числа будет фигурировать запятая, то вы получите ошибку несовпадения типов при попытке преобразовать такую строку в целое число (кстати, эта ошибка возникнет и при попытке использования CDbl или CSng для преобразования строки в вещественное число, а также и при использовании Int или Fix).
О функциях Val, CDbl и CSng
Эти функции хотя и не имеют отношения к преобразованию в целые числа, но стоит их рассмотреть. Есть тут свои нюансы. CDbl и CSng аналогичны CLng и CInt. CDbl преобразовывает аргумент в вещественное число типа Double, CSng соответственно в Single. Естественно надо обращать внимание на попадание аргумента в диапазон представления и на правильность разделителя целой и дробной частей. А вот Val…
Функция Val возвращает число, содержащееся в строке аргументе как числовое значение соответствующего типа. Данная функция будет пытаться преобразовать строку до тех пор, пока не встретит символ, который не может быть распознан как часть числа. В частности функция прекрасно понимает префикс &O для чисел в восьмеричной системе записи и &H для шестнадцатеричных чисел. А вот пробелы Val просто игнорирует. Еще одним нюансом является тот факт, что в качестве разделителя используется только точка «.» вне зависимости от национальных настроек.
Таким образом, функция Val преобразовывает строки следующим образом:
Строка |
Число |
Примечания |
" 1 2 34569" |
1234569 |
После отбрасывания пробелов получаем целое число 1234569. |
" &ha bc d eff" |
180150015 |
После отбрасывания пробелов получаем шестнадцатеричное число &HABCDEFF, которое после преобразования в десятичную форму равно 180150015. |
" &O1 2 34569" |
-22738 |
После отбрасывания пробелов получаем восьмеричное число &O1234569, которое после преобразования в десятичную форму равно -22738. |
" 1 2 345,69" |
12345 |
После отбрасывания пробелов функция пытается разобрать число и останавливается на символе «,», после чего и возвращает 12345. |
" 1 2 345.69" |
12345.69 |
В отличие от предыдущего случая здесь символ «.» является законным разделителем целой и дробной частей числа, поэтому результатом будет 12345.69. |
" 1 2 34569 number" |
1234569 |
Здесь разбор числа будет остановлен на первой встреченной букве «n», а все что до нее преобразовывается в число 1234569. |
Особое внимание стоит уделить разделителям целой и дробной частей. Если функции CDbl и CSng вызывают ошибку, если в строке содержится запятая вместо точки, а разделителем в национальных настройках является запятая, то Val просто не будет разбирать строку дальше и вернет целую часть числа. Поэтому будьте бдительны при вводе пользователем данных. Введенные пользователем данные лучше всего преобразовывать с учетом национальных настроек или же сообщать пользователю о некорректном вводе. Кстати, простейший способ получить символ разделения целой и дробной частей – вызвать функцию Format следующим образом
Format$(0, ".")
Этот вызов вернет текущий разделитель целой и дробной частей числа.
Об округлении
Для округления используется функция Round. Она возвращает число с заданным количеством цифр после запятой. Однако есть один нюанс. Функция Round именно округляет (что собственно видно из названия). То есть вызов Round(1.15, 1) даст результат 1.2. А иногда возникает ситуация, когда необходимо отбросить лишние цифры, то есть для числа 1.15 получить 1.1. Здесь надо пользоваться конструкцией вида:
Fix(10*n)/10
Здесь вместо 10 должна использоваться степень 10, соответствующая количеству оставляемых цифр после запятой. Универсальный вариант будет таким:
Fix(10^numdecimalplaces*n)/10^numdecimalplaces
Обратите внимание, что здесь используется именно функция Fix, а не Int, которая для отрицательных чисел будет работать некорректно.