【问题标题】:math: scale coordinate system so that certain points get integer coordinates数学:缩放坐标系,使某些点获得整数坐标
【发布时间】:2011-02-02 11:45:07
【问题描述】:

这更像是一个数学问题。尽管如此,我正在寻找伪代码中的算法来解决它。

给定的是一个一维坐标系,有多个点。点的坐标可能是浮点数。

现在我正在寻找一个缩放此坐标系的因子,以便所有点都在固定数字上(即整数坐标)

如果我没记错的话,这个问题应该有解决方案,只要点数不是无限的。

如果我错了并且这个问题没有解析解,我对尽可能接近解的算法感兴趣。 (即坐标看起来像 15.0001)

如果您对具体问题感兴趣: 我想克服 adobe flash 中众所周知的像素捕捉问题,如果整个舞台被缩放,它会在位图的边界处切割半像素。我想找到一个理想的舞台比例因子,使我的位图被放置在整个(屏幕)像素坐标上。

由于我在舞台上放置了两个位图,因此每个方向 (x,y) 上的点数将为 4。

谢谢!

【问题讨论】:

  • 没有通用的解决方案,例如无理数。
  • @Jaime Pardos:但无理数不能表示为(有限)浮点数,这似乎是他所拥有的。 @OP:一般但实际上可能很愚蠢的解决方案是将浮点数表示为整数的分数,直到达到所需的精度。那么你的比例因子就是所有分母的乘积。
  • 谢谢,是的,让我们排除这个问题的无理数

标签: algorithm math geometry


【解决方案1】:

按照建议,您必须将浮点数转换为有理数。固定一个容差 epsilon,并为每个坐标找到其在 epsilon 内的最佳有理逼近

therethis section 中概述了算法和定义。

将所有坐标转换为有理数后,比例将由分母的最小公倍数给出。

请注意,后一个数字可能会变得非常大,因此您可能需要尝试使用 epsilon 来控制分母。

【讨论】:

    【解决方案2】:

    如果我处于你的情况,我自己的倾向是使用有理数而不是浮点数。 您正在寻找的算法是找到最小的公分母。

    【讨论】:

    • 谢谢,但这是不可能的,因为一旦缩放舞台,flash 就会引入浮点坐标。
    • 浮点数就其本质而言是理性的。尽管利用它们允许的全部精度范围可能不切实际。
    • 您可以将浮点数视为有理数(顺便说一句,它是有理数)。
    【解决方案3】:

    浮点数是一个整数,乘以 2 的幂(幂可能是负数)。

    因此,在您的输入中找到两个的最大必要幂,这将为您提供一个可行的比例因子。 2 的幂不仅是浮点数的指数的 -1 倍,而且还不止这个数(根据有效数字中最低有效 1 位的位置)。

    这也是最优的,因为如果 x 乘以 2 的幂是奇数,那么 x 在其浮点表示中已经是最简单的有理形式,没有更小的整数可以乘以 x 得到一个整数。

    显然,如果您在输入中混合了大小值,那么生成的整数往往会大于 64 位。所以有一个分析解决方案,但考虑到您想要对结果做什么,它可能不是一个很好的解决方案。

    请注意,这种方法将浮点数视为精确的表示,而事实并非如此。通过将每个浮点数表示为分母较小的有理数(在某个定义的公差范围内),然后取所有分母的最小公倍数,您可能会得到更合理的结果。

    但问题在于近似过程 - 如果输入浮点数是 0.334[*],那么我通常无法确定给我它的人是否真的意味着 0.334,或者它是否是 1/3不准确。因此,我不知道是使用 3 的比例因子并说缩放结果为 1,还是使用 500 的比例因子并说缩放结果为 167。这只是 1 个输入,别介意一堆.

    使用 4 个输入并允许最终容差为 0.0001,您也许可以找到与每个输入最接近且具有某个最大分母的 10 个有理数,然后尝试 10^4 种不同的可能性,并查看生成的比例因子是否为您提供了任何值离整数太远了。蛮力似乎很讨厌,但你至少可以在你去的时候限制搜索。 “最大分母”也可以用分解中存在的素数来表示,而不仅仅是数字,因为如果你能在其中找到很多公因数,那么它们的 lcm 会更小,因此与整数的偏差也会更小缩放后。

    [*] 不是说 0.334 是一个精确的浮点值,而是那种东西。小数示例更容易。

    【讨论】:

      【解决方案4】:

      如果你说的是single precision floating point数字,那么根据维基百科,数字可以这样表示:

      从这个公式你可以推断出,如果你乘以 2127+23,你总是得到一个整数。 (实际上,当e0 时,您必须对“次正规”数字的特殊范围使用另一个公式,因此 2126+23 就足够了。有关详细信息,请参阅链接的维基百科文章。)

      要在代码中执行此操作,您可能需要执行一些bit twiddling 以从浮点值的位中提取上述公式中的因子。然后,您将需要某种对无限大小数字的支持来表示缩放的整数结果(例如 .NET 中的BigInteger)。大多数语言/平台中的普通原始类型通常被限制为小得多的大小。

      【讨论】:

        【解决方案5】:

        这确实是统计推断与降噪相结合的问题。这是我将很快尝试的方法。我假设您正在尝试获得规则间隔的二维网格,但类似的方法可以在 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 > x' 或 x = x' 和 y > y',则通过增加字典顺序 (x,y) > (x',y') 对向量进行分组。取最小的 (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)) = (round(M0), round(M1))。

        现在对方程的向量进行整数的最小二乘拟合 (x,y) = (ux,uy) m0(x,y) (u0x,u0y) + m1(x,y) (u1x ,u1y) 找到 (ux,uy)、(u0x,u0y) 和 (u1x,u1y)。这标识了网格。

        测试此匹配以确定是否所有点都在此拟合的给定阈值内(可能为此使用相同的阈值 epsilon)。

        同一例程的一维版本也应该在光谱仪上的一维中工作,以识别声纹中的基频。仅在这种情况下,ux(替换 (ux,uy))的假设值仅为 0,并且只是在寻找齐次方程 x = m0(x) u0x 的拟合。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2016-11-21
          相关资源
          最近更新 更多