Числа с плавающей точкой в качестве индексов
Предположим, что матрица А имеет размер 2 х 2, Для того чтобы обратиться к элементам матрицы, могут применяться как жестко заданные в тексте программы индексы, так и значения, вычисляемые динамически в ходе ее выполнения, в том числе нецелые, как показано ниже:
-->А = testmatrix("hilb", 2)
А =
4. - 6.
6. 12.
-->А( 2, [1.0 1.1 1.5 1.9] )
ans =
6. - 6. - 6. - 6.
Этот пример демонстрирует, что все значения 1.0, 1.1, 1.5 и 1.9 округляются до 1, как при использовании функции int, округляющей дробные значения в сторону 0. Например, результатом каждого следущего вызова: int (1.0),int (1.1), int (1.5) и int (1.9) - будет значение 1, а выражения int (-1.0), int (-1.1), int (-1.5) и int (-1.9) возвращают число -l.
Заметим, что округление происходит в соответствии с особенностями работы функции int, а не floor, которая в отличие от int отрицательные значения округляет в меньшую сторону. В самом деле, предположим, что А представляет матрицу 4х4, например, созданную в результате вызова А = testmatrix ("hilb”, 4). Функция triu (А,к) возвращает верхнюю треугольную часть переданной ей матрицы А, лежащую выше k-ой диагонали. Команды triu(A, -1), triu(A, int (-1.5)) и trioi(А,-1.5) возвращают один и тот же результат, в то время как инструкция triu(A,f loor (-1.5)) эквивалентна triu(A, -2).
Такое поведение может показаться странным, но способствует единообразию языка Scilab. Действительно, при обращении к элементам матрицы с использованием переменных в качестве индексов, чаще всего типом переменной будет являться число с плавающей точкой. В этом случае конверсия происходит посредством функции int. Следующий фрагмент иллюстрирует сказанное:
-->i = 2
i =
2.
— >j = 1
j =
1.
—>A(i, j)
ans =
- 6.
Обратите внимание, что в этот примере переменные i и j имеют тип с плавающей точкой.
Иногда использование чисел с плавающей точкой в качестве индексов может приводить в неожиданным результатам, например:
-->ones(1,1) ans =
1.
-->ones(l, (1 - 0.9) * 10) ans = []
При отсутствии ошибок округления, обусловленных конечной разрядностью представления чисел в памяти компьютера, значение выражения (1 — 0.9) * 10 равнялось бы 1, и в приведенном примере мы получили бы матрицу 1 х 1. Однако в действительности команда ones (1, (1-0 .9) *10) возвращает пустую матрицу, так как в результате округления числа (1 — 0.9) * 10 с использованием функции int получаем 0:
-->int((l - 0.9) * 10) ans = 0.
Как уже было сказано, причиной тому являются ошибки двоичного представления дробных чисел в результате двоичное представление числа 1-0.9 несколько меньше 0.1, а будучи умноженным на 10, несколько меньше 1, вчём позволяет убедиться следующий пример:
-->format(25)
-->1 - 0.9
ans =
0.0999999999999999777955
-->(1 - 0.9) * 10
ans =
0.9999999999999997779554
На практике, при вычислении индексов, не следует применять числа, которые не имеют точного представления в форме с плавающей точкой. В частности, точные результаты дают обычные арифметические операции с целыми числами в пределах интервала [—252, 252].