Лучший алгоритм для предотвращения потери точности?

Я полагаю, вы используете пакет Intervention Image. Однако нет необходимости помещать все изображения в этот пакет. Если вы это сделаете, пакет обработает изображение, и это займет много времени.

Если вы просто хотите вернуть изображение, вы можете сделать это с помощью встроенного файла ответа .

return response()->file('images/test.jpg');

Это загрузит файл прямо из файловой системы и будет намного быстрее.

7
задан Coral Doe 28 September 2012 в 08:08
поделиться

4 ответа

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

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

a = 1,000,000;
do 100,000,000 time:
   a += 0.01;

если 0.01 меньше, чем самая низкая цифра мантиссы, то цикл ничего не делает, и конечный результат == 1,000,000, но если Вы делаете это как это:

a = 0;
do 100,000,000 time:
   a += 0.01;
a += 1,000,000;

Чем небольшое число медленно растут, и Вы, более вероятно, закончите с чем-то близко к == 2,000,000, который является правильным ответом.
Это - конечно, экстремальный пример, но я надеюсь, что Вы получаете идею.

5
ответ дан 6 December 2019 в 21:21
поделиться

Я должен был забрать класс численных данных, когда я был старшекурсником, и это было полностью болезненно. Во всяком случае IEEE 754 является стандартом с плавающей точкой, обычно реализованным современными центральными процессорами. Полезно понять основы его, поскольку это дает Вам большую интуицию о том, какой не сделать. Упрощенное объяснение его состоит в том, что компьютеры хранят числа с плавающей точкой в чем-то как основа 2 экспоненциальных представления с постоянным числом цифр (биты) для экспоненты и для мантиссы. Это означает это, чем больше абсолютное значение числа, тем менее точно оно может быть представлено. Для 32-разрядных плаваний в IEEE 754 половина возможных комбинаций двоичных разрядов представляет между-1 и 1, даже при том, что числа до приблизительно 10^38 являются представимыми с 32-разрядным плаванием. Для значений, больше, чем 2^24 (приблизительно 16,7 миллионов), 32-разрядное плавание не может представить все целые числа точно.

То, что это означает для Вас, - то, что Вы обычно хотите избежать следующего:

  1. Наличие промежуточных значений быть большим, когда окончательный ответ, как ожидают, будет маленьким.
  2. Добавление/вычитание небольших чисел к/от большим количествам. Например, если Вы записали что-то как:

    для (пускают в ход индекс = 17000000; индекс <17000001; индексируйте ++) {}

Этот цикл никогда не завершался бы, becuase 17,000,000 + 1 округляется в меньшую сторону до 17,000,000. Если у Вас было что-то как:

float foo = 10000000 - 10000000.0001

Значение для нечто было бы 0, не-0.0001, из-за погрешности округления.

4
ответ дан 6 December 2019 в 21:21
поделиться

Другая вещь избежать вычитает количества, которые почти равны, поскольку это может также привести к увеличенной чувствительности к ошибке округления. Для значений около 0, because(x) будет близко к 1, таким образом, 1/cos (x) - 1 будет одним из тех вычитаний, которых требуется избежать, если это возможно, таким образом, я скажу, что (a) нужно избежать.

1
ответ дан 6 December 2019 в 21:21
поделиться

Мой вопрос в том, какие еще общие ситуации, которые я должен искать за и то, что считается "хорошим" методы приближения к ним?

Есть несколько способов получить серьезную или даже катастрофическую потерю точности.

Самая важная причина заключается в том, что числа с плавающей запятой имеют ограниченное количество цифр, например, двойные имеют 53 бита. Это означает, что если у вас есть «бесполезные» цифры, которые не являются частью решения, но должны быть сохранены, вы теряете точность.

Например (мы используем десятичные типы для демонстрации):

2.598765000000000000000000000100 -

2.598765000000000000000000000099

Интересная часть - это 100-99 = 1 ответ. Поскольку 2,598765 в обоих случаях равно не меняет результат, а тратит 8 цифр. Намного хуже, потому что компьютер не знает, что цифры бесполезны, он вынужден хранить их и запихивает после них 21 ноль, трата всего 29 цифр. К сожалению, нет возможности обойти это для различий, но есть и другие случаи, например, exp (x) -1, которая очень часто встречается в физике.

Функция exp около 0 почти линейна, но она заставляет 1 в качестве ведущей цифры. Итак, с 12 значащие цифры exp (0.001) -1 = 1.00100050017 - 1 = 1.00050017e-3

Если мы используем вместо этого функцию expm1 (), используйте ряд Тейлора:

1 + x + x ^ 2/2 + x ^ 3 / 6 ... -1 =

x + x ^ 2/2 + x ^ 3/6 =: expm1 (x)

expm1 (0,001) = 1,00500166667e-3

Намного лучше.

Вторая проблема - это функции с очень крутым наклоном, например касательной к x вблизи pi / 2. tan (11) имеет наклон 50000, что означает, что любое небольшое отклонение, вызванное ошибками округления перед усилением будет в 50000 раз! Или у вас есть особенности, если, например, результат приближается к 0/0, что означает, что он может иметь любое значение.

В обоих случаях вы создаете заменяющую функцию, просто заменяя исходную функцию. Бесполезно выделять различные подходы к решению, потому что без обучения вы просто не «увидите» проблему в первую очередь.

Очень хорошая книга для изучения и обучения: Форман С. Эктон: Реальные вычисления стали реальностью

2
ответ дан 6 December 2019 в 21:21
поделиться
Другие вопросы по тегам:

Похожие вопросы: