这更像是一个数学问题。 nonethelesse我正在寻找伪代码中的算法来解决它。
给定的是一维坐标系,具有多个点。点的坐标可能处于浮点状态。
现在我正在寻找一个缩放此坐标系的因子,以便所有点都在固定数字上(即整数坐标)
如果我没有弄错的话,只要点数不是无限的,就应该有解决这个问题的方法。
如果我错了并且没有针对这个问题的解析解,我感兴趣的是一种尽可能接近解决方案的算法。 (即坐标看起来像15.0001)
如果您对具体问题感兴趣: 我想克服adobe flash中众所周知的像素拍摄问题,如果整个舞台被缩放,那么在位图边界处会切割半像素。我想找到一个理想的舞台缩放因子,使我的位图放在整个(屏幕)像素坐标上。
因为我在舞台上放置了两个位图,所以每个方向(x,y)的点数为4。
谢谢!
答案 0 :(得分:6)
根据建议,您必须将浮点数转换为有理数。修复公差epsilon,并为每个坐标在epsilon中找到它的最合理逼近。
there中列出了this section的算法和定义。
将所有坐标转换为有理数后,缩放由分母的最小公倍数给出。
请注意,后一个数字可能变得非常庞大,因此您可能需要尝试使用epsilon来控制分母。
答案 1 :(得分:1)
如果我在你的情况下,我自己的倾向是使用有理数而不是浮点数。 您正在寻找的算法是找到最低的共同点。
答案 2 :(得分:1)
浮点数是一个整数,乘以2的幂(幂可能是负数)。
因此,在输入中找到两个最大的必要功率,这将为您提供一个可行的比例因子。 2的幂不仅仅是浮点数的-1倍,它还有几个(根据有效数字中最低有效位1的位置)。
它也是最优的,因为如果x
乘以2的幂是一个奇整数,那么其浮点表示中的x
已经是最简单的有理形式,那么就没有可以乘以的较小整数{{ 1}}来得到一个整数。
显然,如果输入中混合了大小值,那么得到的整数往往会大于64位。所以有一个分析解决方案,但考虑到你想对结果做什么,也许不是一个非常好的解决方案。
请注意,此方法将浮动视为精确表示,而不是。通过将每个浮点数表示为具有较小分母(在某个定义的容差范围内)的有理数,然后取所有分母的最低公倍数,可以获得更明智的结果。
那里的问题是近似过程 - 如果输入浮点数是0.334 [*]那么我一般不能确定给它的人是否真的意味着0.334,或者它是否是1/3不准确。因此,我不知道是否使用比例因子为3并且说缩放结果是1,或者使用比例因子500并且说缩放结果是167.并且这只是1输入,更不用说它们中的一堆
使用4个输入并允许最终容差为0.0001,您可以找到每个输入具有特定最大分母的10个最接近的有理数,然后尝试10 ^ 4个不同的可能性并查看得到的比例因子是否为您提供任何值离整数太远了。蛮力似乎很讨厌,但你可能至少能够在你去的时候限制搜索。 “最大分母”也可以用因子分解中存在的素数来表示,而不仅仅是数字,因为如果你能在它们中找到很多共同因素那么它们将具有更小的lcm,因此与整数的偏差更小缩放后。
[*]不是说0.334是一个确切的浮点值,而是那种东西。十进制示例更容易。
答案 3 :(得分:1)
如果您正在谈论single precision floating point号码,那么根据维基百科可以表示这个数字:
从这个公式可以推断出,如果乘以2 127 + 23 ,你总是得到一个整数。 (实际上,当e
为0
时,您必须使用另一个公式来处理特殊范围的“次正规”数,因此2 126 + 23 就足够了。请参阅链接的维基百科文章详情。)
要在代码中执行此操作,您可能需要执行一些bit twiddling以从浮点值中的位中提取上述公式中的因子。然后,您需要某种支持无限大小的数字来表示缩放的整数结果(例如.NET中的BigInteger)。大多数语言/平台中的普通原始类型通常限制为更小的尺寸。
答案 4 :(得分:1)
统计推断与降噪相结合确实存在问题。这是我即将尝试的方法。我假设您试图获得一个规则间隔的二维网格,但类似的方法可以在3维或更多维度的规则间隔网格上工作。
首先列出所有差异并注意(dx,dy)和(-dx,-dy)表示相同的位移,因此存在等价关系。将那些在预先指定的阈值(epsilon)内的差异分组。 Epsilon应该足够大以捕获由于随机噪声或图像分辨率不足而导致的测量误差,但足够小以至于不会意外地组合群集。
按照平均大小对群集进行排序(dr = root(dx ^ 2 + dy ^ 2))。
如果原始网格确实是有规律地间隔并由两个独立的基矢量生成,那么两个最小的线性独立的簇将表示如此。最小的簇是以(0,0)为中心的簇。下一个最小的聚类(dx0,dy0)具有第一个基础向量,最多+/-符号(-dx0,-dy0)表示相同的位移,召回。
由于是(dx0,dy0)的倍数,下一个最小的簇可以线性地依赖于此(直到阈值epsilon)。找到不是(dx0,dy0)倍数的最小簇。调用它(dx1,dy1)。
现在你有足够的标记原始矢量。通过增加词典顺序(x,y)>对矢量进行分组。 (x',y')如果x> X'或者x = x'和y> ý&#39 ;.取最小的(x0,y0)并为其分配整数(0,0)。取所有其他(x,y)并找到分解(x,y)=(x0,y0)+ M0(x,y)(dx0,dy0)+ M1(x,y)(dx1,dy1)并分配它是整数(m0(x,y),m1(x,y))=(圆(M0),圆(M1))。
现在对方程的向量进行整数的最小二乘拟合(x,y)=(ux,uy)m0(x,y)(u0x,u0y)+ m1(x,y)(u1x ,u1y) 找到(ux,uy),(u0x,u0y)和(u1x,u1y)。这标识了网格。
测试此匹配以确定所有点是否在此拟合的给定阈值内(可能为此目的使用相同的阈值epsilon)。
该相同程序的1-D版本也应在光谱仪上以1维方式工作,以识别声纹中的基频。只有在这种情况下,ux(取代(ux,uy))的假设值才为0,只有一个只是寻找拟合齐次方程x = m0(x)u0x。