我在FORTRAN 77中编写模拟,我需要从一些实验数据中获取参数值。数据来自互联网数据库,所以我提前下载了它,但没有简单的数学模型可以用来连续提供数值 - 我只有离散的数据点。但是,我需要知道x轴上任何值的这个参数,而不仅仅是数据库中的离散值。
为了简化,您可以说我知道f(x)
的所有整数值x
的值,并且需要一种方法来查找任何真实f(x)
的{{1}}价值(从不在我知道的最小或最大x
之外)。
我的想法是获取数据并进行线性插值,以便能够获取参数值;在伪代码中:
x
为了实现这一点,我需要对数据点进行某种查找。我可以通过从数据库获取所有整数double xd = largest_data_x_lower_than(x)
double slope = (f(xd+dx)-f(xd))/dx // dx is the distance between two x values
double xtra = x-xd
double fofx = f(xd)+slope*xtra
的值来轻松查找xd
,以便x
和xd = int(x)
,但我仍然不知道如何实现查找dx = 1
。
实施此方法的好方法是什么?
在一次模拟运行期间,该值将被提取10 ^ 7到10 ^ 9次,因此性能至关重要。换句话说,每次我需要f(xd)
的值时从IO读取都不是一种选择。
我目前在一个文本文件中有数据点,每行有一对(制表符分隔的)f(xd)
,所以解决方案的奖励点也提供了一种从这里获取数据的平滑方式无论它需要什么形状。
答案 0 :(得分:2)
你说你拥有所有整数的值。对于从i, f(i)
到i
的所有整数M
,您是否有N
对?然后将值f(i)
读入尺寸为y
的数组M:N
。除非值的数量是巨大的。对于M
和N
之间的实际值,很容易索引到数组并在最近的值对之间进行插值。
为什么要使用FORTRAN 77? Fortran 90/95/2003已与我们合作多年了......
编辑:在评论中回答问题,重新如何在FORTRAN 77中只读取一次数据值,而不必在长链调用中将它们作为参数传递。技巧1:在程序启动时,将它们读入数组,该数组位于命名的公共块中。技巧2:第一次调用返回f(x)
的函数时,将值读入同样位于SAVE
语句的局部变量中。使用SAVEd逻辑指定该函数是否在第一次调用时。一般来说,我更喜欢技术2更“本地”,但它不是线程安全的。如果你是并行进行模拟,第一种技术可以在程序进行多线程之前在启动阶段完成。
以下是使用SAVE
:fortran SAVE statement的示例。 (在Fortran 95表示法中......转换为FORTRAN 77)。将数据读取放入IF
块中的数组中。
答案 1 :(得分:0)
您可能想要一种内插或拟合数据的方法,但您需要更具体地说明数据的维度,数据的行为方式,访问数据的方式(例如,您的下一个请求总是接近最后一个),如何制作网格(均匀间隔,随机或其他方式),以及您需要数据以便能够知道哪种方法最适合您。
但是,如果现有数据集非常密集且接近线性,那么您当然可以进行线性插值。
答案 2 :(得分:0)
使用您的数据库(文件),您可以创建一个数组fvals
,fvals(ii)
为函数f(xmin + (ii-1) * dx)
。 x值xx
与数组索引之间的映射为ii = floor((xx - xmin) / dx) + 1
。知道ii
后,您可以使用它周围的点进行插值:使用ii
和ii+1
进行线性插值或进行一些高阶多项式插值。对于后者,您可以使用Numerical Recipes中相应的polint例程。见第103页。