Извлечение параметров округления из набора значений с плавающей запятой

#ruby #crystal-lang #floating-point-conversion

#рубиновый #crystal-lang #преобразование с плавающей запятой #ruby

Вопрос:

Учитывая следующие значения с плавающей запятой :

 n00.0, n0.0, n.0, 0.n, 0.0n, 0.00n, 0.000n 
  

где n может быть 1, 2 или 5, какой самый умный и быстрый способ извлечь соответствующие целочисленные значения, которые будут использоваться в качестве параметров округления

 -2, -1, 0, 1, 2, 3, 4 
  

На данный момент я использую хэш-таблицу: быстро, но, по-моему, не так умно!

Комментарии:

1. В настоящее время я использую Crystal-Lang (или Ruby). Значение с плавающей запятой на данный момент, но может быть строкой.

2. Реализация Number#humanize должна дать некоторое вдохновение: github.com/crystal-lang/crystal/blob /…

3. -Math.log10(value).floor получилось! Более чем в 60 раз быстрее, чем хэш. Спасибо

Ответ №1:

Я подумал, что использование хэша — хороший подход, и скептически относился к тому, что он будет превзойден -Math.log10(k).floor , поэтому я провел следующий тест.

Создайте хэш

 h = { 100.0=>-2, 10.0=>-1, 1.0=>0, 0.1=>1, 0.01=>2,
      200.0=>-2, 20.0=>-1, 2.0=>0, 0.2=>1, 0.02=>2,
      500.0=>-2, 50.0=>-1, 5.0=>0, 0.5=>1, 0.05=>2 } 
  

Постройте тестовый массив для бенчмарка (15 миллионов элементов)

 n = 1_000_000
(arr = h.keys.flat_map { |k| [k]*n }.shuffle).size
  #=> 15_000_000 
arr.first(10)
  #=> [20.0, 0.02, 5.0, 0.5, 0.02, 0.05, 500.0, 50.0, 50.0, 20.0] 
arr.last(10)
  #=> [500.0, 0.5, 0.1, 20.0, 0.01, 0.1, 500.0, 50.0, 0.05, 0.5] 
  

Выполнить тест

 require 'fruity'

compare(
  hash:  -> { arr.each { |k| h[k] } },
  log10: -> { arr.each { |k| -Math.log10(k).floor } }
)
Running each test once. Test will take about 42 seconds.
hash is faster than log10 by 60.0% ± 10.0%
  

Комментарии:

1. Портировал ваш бенчмарк на Crystal, и там хэш, по-видимому, в 4 раза медленнее, но я не уверен на 100%, что я обманул LLVM из-за исключения всего кода (самый наивный порт понимает, что результат операции log10 никогда не считывается и просто полностью устраняет его, что, вероятно, является 60-кратным комментариемпришло из).

2. Обратите внимание, что вопрос также помечен как crystal-lang . Crystal — это язык программирования, реализованный как интерфейс LLVM , см. crystal-lang.org