C浮动:如何围绕二维几何图形(线)移动

C浮动:如何围绕二维几何图形(线)移动,c,floating-point,integer,precision,computational-geometry,C,Floating Point,Integer,Precision,Computational Geometry,我目前正在用C语言做一些2D几何,主要是直线相交。这些线有各种各样的斜率:从0.001到1000(例如,我甚至不知道) 到目前为止,我一直在使用浮点,不必担心该值是非常小(然后浮点将00011存储为1e-3,不进行舍入)还是非常高(然后1001将存储为1e3),在这两种情况下,相关精度几乎没有损失 但现在我想尝试不使用浮点数,使用整数。如何保持我的计算精度?我可以有一个标志告诉我,坡度是大还是小,然后考虑第十的大斜坡和十倍的小坡度,所以四舍五入是没有问题的小斜坡和没有溢出的情况下,大斜坡。但那感

我目前正在用C语言做一些2D几何,主要是直线相交。这些线有各种各样的斜率:从0.001到1000(例如,我甚至不知道)

到目前为止,我一直在使用浮点,不必担心该值是非常小(然后浮点将00011存储为1e-3,不进行舍入)还是非常高(然后1001将存储为1e3),在这两种情况下,相关精度几乎没有损失

但现在我想尝试不使用浮点数,使用整数。如何保持我的计算精度?我可以有一个标志告诉我,坡度是大还是小,然后考虑第十的大斜坡和十倍的小坡度,所以四舍五入是没有问题的小斜坡和没有溢出的情况下,大斜坡。但那感觉像是头痛

基本上,我仍然需要能够区分0.2和0.4的斜率,以及1000和2000的溢出斜率(假设ints溢出在1000-这里的问题更少)

还有其他想法吗?

将斜率存储为一对整数

struct slope {
  int delta_y;
  int delta_x;
};
这允许范围广泛的坡度,如
0
+/-1/INT\u MAX…+/-INT_MAX
,甚至垂直。通过仔细的编码,可以进行精确的计算

延迟信用:这很像。

如果您想以通用方式使用int,请查找

您还可以设计算法,以便以不需要次整数精度的方式进行每次计算(例如查找和绘制算法)


对于您的特定问题,您可以尝试将商和分数分开,换句话说,使用有理数。或者换句话说,将δX和δY作为两个数字。

一般来说,对于任意方向的线,不建议使用斜率/截距表示法
Y=mx+p
,而是使用隐式方程
a X+b Y+c=0
。后者更为各向同性,支持垂直线,并为缩放系数提供了额外的灵活性

根据@chux的答案,系数可以是delta,
Dy x-Dx y+c=0
(假设直线由两点定义,
Dx
Dy
很可能不会溢出)。在
c
上仍然可能出现溢出,您可以使用变量
Dy(x-x0)-Dx(y-y0)=0

无论如何,交叉点等中间计算可能需要更大的范围,即双长度整数

标记大/低值的想法有点适得其反:它实际上是一种进行浮点运算的原始方法,即将刻度与尾数分开。通过这种方式,您将以某种方式重新设计一个煽动点系统,其功能不如内置式系统,并且会耗费您的汗水和眼泪


不幸的是,无法避免高范围算法。事实上,两条直线的交点由Cramer公式给出

x = (c b' - c' b) / (a b' - a' b),
y = (a c' - a' c) / (a b' - a' b)

其中待评估的产品比初始系数大一个数量级。这是因为准平行线有很远的交叉点。

除了同时存储上升和上升?使用
double
和不精确度?为什么需要超过15位十进制有效数字的准确度?这个精度足以测量从这里到冥王星的距离(厘米)。在计算几何时,你总是会有不精确性,因为你总是有无理数。@DavidBowling注意:所有整数和有限浮点值都是有理数。确实,许多整型/浮点型计算与数学结果不同。@chux--当然。我的观点是,一般来说(在R^n中)计算几何必须涉及无理数。例如,坡度为m=√2不能以斜率截距形式或使用方向向量(即参数形式)表示,而无非有理性。使用有理点的子集是避免这些困难的一种方法,但代价是限制查询对象。我认为在这里管理不精确是不可避免的;虽然我认为这最终是一个目标的问题。这是一个好主意,特别是如果你可以使用
slope
实例,而不必计算梯度。不过,我可以考虑将其中一个成员定义为代码>未签名的< /C> >,但我想您可以在结构上排序这种类型,因为您可能希望“正常化”输入(例如{ 2,-4 }与{ 1, 2 }相同)。@芭丝谢芭同意“一个字段<代码>未签名< /代码>和<代码> int分子;无符号分母。不过,这会使一些计算变得有点棘手<代码>整数增量y,增量x似乎是向OP介绍这个想法的一个好方法。你也可能会陷入困境,不必要地将有符号参数提升为无符号参数的类型。OP正在进行直线相交,使用叉积是避免计算坡度时被零除陷阱的一种简单方法。有一种使用叉积的求交算法,其中被零除只能发生在直线平行的情况下,当没有交点时,这是一种可以测试的特殊情况。