如何缩小一些任意数字之间的差距?

时间:2019-10-31 21:07:09

标签: algorithm rounding

我正在尝试找到一种算法来消除一些半随机数之间的间隙,例如,如果存在具有close值的间隙,它们将是相同的。 例如,如果我们将“ 109 102 212 198 99 802”作为空白,则四舍五入为“ 100 100 200 200 100 100 800”。 假定所有舍入的间隙将为(2 ^ n)*(最小间隙),其中n是一个非负整数。在上面的示例中,间隙大约为100(最小),200、400、800。

1 个答案:

答案 0 :(得分:1)

实际上,我想编写代码将唱歌曲目转换为乐谱。为此,我找到了相邻音符之间的间隔,然后我需要算法来舍入这些间隔。 我已经做到了,而且我认为效果很好。 首先,我发现主要差距的值,例如在“ 102 103 402 409 390 398 100 200 408”中,主要差距约为400(平均值为402 409 390 398 408),然后我将其持续时间设为1并进行比较另一个。 102的持续时间将为0.25,依此类推。

编辑:第一,我使用了一些python库来处理.mp3文件,并以毫秒为单位查找频率变化的时刻及其对应的持续时间。由于这些时间并不精确,因此我需要四舍五入,因此可以为它们指定一种音符符号。

def roundOff(diffs):
        global major_element, ref_offset, divide_flag, measured_time, measured_note
        major_element = findMajor(diffs)
        for element in diffs:
            divide_flag = False
            measured_time = 0
            measured_note = 0
            note_duration.append(noteFinder(element, ref_offset))
        return note_duration

上面的函数获取间隙作为输入并返回其相应的音符持续时间。 我发现主要差距如下:

def findMajor(diffs):
    diffs_copy = diffs.copy()
    diffs_copy.sort()
    this = 0
    for element in diffs_copy:
        if isNear(element, this):
            temp_this = (this*elements_in_gap[this] + element)/(elements_in_gap[this] + 1)
            elements_in_gap[this] += 1
            elements_in_gap[temp_this] = elements_in_gap.pop(this)
            this = temp_this
        else:
            this = element
            elements_in_gap[this] = 1

    return max(elements_in_gap, key = element_in_gap.get)

首先,它对间隙列表进行排序,并将“ this”作为我们要检查的间隙的代表值(初始值为0),在每个步骤中,它检查新间隙是否在“ this”附近然后修改“ this”并增加“ this”集中的间隔数,但是如果不接近,则将“ this”更改为新元素,并将新“ this”的初始数量(:|)更改为1并执行相同的操作。 最后,将值最大的键作为主要空白返回。

isNear函数是这样的:

def isNear(a, b):
    if a < b+b*tolerance and a > b-b*tolerance:
        return True
    return False

在这种情况下,将公差设置为0.1是适当的。 noteFinder查找与主要差距为1(ref_offset)有关的每个差距的音符。

def noteFinder(diff_time, offset):
    global measured_time, measured_note, divide_flag, major_element
    if isNear(diff_time, measured_time):
        return measured_note
    else:
        if not divide_flag:
            if diff_time > measured_time:
                measured_time += offset*major_element
                measured_note += offset
                return noteFinder(diff_time, offset)
            else:
                offset /= 2
                measured_time -= offset*major_element
                measured_note -= offset
                divide_flag = True
                return noteFinder(diff_time, offset)
        else:
            offset /= 2
            if diff_time > measured_time:
                measured_time += offset*major_element
                measured_note += offset
                return noteFinder(diff_time, offset)
            else:
                measured_time -= offset*major_element
                measured_note -= offset
                return noteFinder(diff_time, offset)

在每个步骤中将偏移量添加到被测音符上,并将偏移量*主要间隙值添加到测量时间(首先,偏移量为1),直到其间隙值小于测量时间,然后打开divid_flag在每一步中将偏移量除以2,并尝试使其接近于差距值,然后返回多人注释。

这是我建议的方案,如果您有更好的方案,请告诉我。