对数组进行量化,以便仍然量化量化值的子集

时间:2015-04-03 00:29:23

标签: ruby rounding quantization

给定int s的数组我想量化每个值,使得量化值的总和为100.每个量化值也应该是整数。这在整个数组被量化时起作用,但是当量化值的子集加起来时,它不会相对于其余值保持量化。

例如,值44,40,7,2,0,0被量化为47,43,8,2,0,0(其总和为100)。如果取最后4个量化值,则总和为53,与第一个值一致(即47 + 53 = 100)。

但是对于值78,7,7,1,0,0,最后4个量化值(8,8,1,0,0)的总和是17.第一个量化值是84,当添加时到17不等于100.显然,原因是四舍五入。有没有办法调整舍入,以便子集仍然一致?

这是Ruby代码:

class Quantize
  def initialize(array)
    @array = array.map { |a| a.to_i }
  end

  def values
    @array.map { |a| quantize(a) }
  end

  def sub_total(i, j)
    @array[i..j].map { |a| quantize(a) }.reduce(:+)
  end

  private

  def quantize(val)
    (val * 100.0 / total).round(0)
  end

  def total
    @array.reduce(:+)
  end
end

(失败)测试:

require 'quantize'

describe Quantize do
  context 'first example' do
    let(:subject) { described_class.new([44, 40, 7, 2, 0, 0]) }

    context '#values' do
      it 'quantizes array to add up to 100' do
        expect(subject.values).to eq([47, 43, 8, 2, 0, 0])
      end
    end

    context '#sub_total' do
      it 'adds a subset of array' do
        expect(subject.sub_total(1, 5)).to eq(53)
      end
    end
  end

  context 'second example' do
    let(:subject) { described_class.new([78, 7, 7, 1, 0, 0]) }

    context '#values' do
      it 'quantizes array to add up to 100' do
        expect(subject.values).to eq([84, 8, 8, 1, 0, 0])
      end
    end

    context '#sub_total' do
      it 'adds a subset of array' do
        expect(subject.sub_total(1, 5)).to eq(16)
      end
    end
  end
end

1 个答案:

答案 0 :(得分:1)

正如对该问题的评论中所述,量化例程无法正确执行:第二个示例[78, 7, 7, 1, 0, 0]被量化为[84, 8, 8, 1, 0, 0] - 它增加到101而不是100。

这是一种可以产生正确结果的方法:

def quantize(array, value)
  quantized = array.map(&:to_i)
  total = array.reduce(:+)
  remainder = value - total

  index = 0

  if remainder > 0
    while remainder > 0 
      quantized[index] += 1
      remainder -= 1
      index = (index + 1) % quantized.length
    end
  else
    while remainder < 0 
      quantized[index] -= 1
      remainder += 1
      index = (index + 1) % quantized.length
    end
  end

  quantized
end

这解决了您的问题,如问题中所述。麻烦的结果变为[80, 8, 8, 2, 1, 1],它增加到100并保持您描述的子集关系。当然,解决方案可以提高性能 - 但它具有工作和易于理解的优点。