二维字典或查找 table?
2d Dictionary or lookup table?
我不太确定我需要什么。
我将此数据保存在 CSV 文件和 SQL 数据库中。我需要做的是能够使用 table 进行双线性插值。那么当说 d = 2.5 和 HVL = 1.6 时,解决这个问题的最佳方法是什么?我可以执行的计算只是不确定如何从 table、某种形式的 LINQ 语句中 select 适当的数字?
编辑:
对于数字 1.6 和 2.5,我需要 select 它周围的数字作为 2x2 矩阵 (Bilinear interpolation)
谢谢
1) 我取了你矩阵的一小部分,如下所示:
2) 然后我们获取您的矩阵并对其进行动态归一化(参见 cte0),它看起来像这样:
现在,为了性能起见,如果这是一个静态矩阵,我会建议您以这种方式实际存储数据。
3) 给定目标值@X 和@Y,然后我们需要确定所需的行和列(在cte1 中)。结果如下所示:
- 字段和值是所需的 Row/Column 数字
4) 在 cte2 中,我们想要获取 X/Y 范围和值,看起来像这样:
4) 最后的查询是X/Yranges/values的插值小事。我使用 UDF 只是为了方便数学计算。
我应该注意到结果已经过验证,如下图所示:
好的,代码怎么样?
我应该补充一点,我将这些部分保留为 cte,这样您就可以看到各个部分是如何协同工作的。当然,这可以进一步压缩(请参阅下面的编辑)。
Declare @YourTable Table ([y] int,[x1.5] float,[x2.0] float,[x3.0] float,[x4.0] float)
Insert Into @YourTable Values
(1,1.050,1.055,1.057,1.057)
,(2,1.080,1.089,1.097,1.098)
,(3,1.091,1.103,1.114,1.446)
Declare @XML xml = (Select * from @YourTable for XML Raw)
Declare @Y float = 2.5
Declare @X float = 1.6
;with cte0 as (
Select RowNr = Dense_Rank() over (Order By r.value('@y','float'))
,ColNr = Dense_Rank() over (Order By convert(float,replace(attr.value('local-name(.)','varchar(100)'),'x','')))
,Y = r.value('@y','float')
,X = convert(float,replace(attr.value('local-name(.)','varchar(100)'),'x',''))
,V = attr.value('.','float')
From @XML.nodes('/row') as A(r)
Cross Apply A.r.nodes('./@*') AS B(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('y') )
,cte1 as (
Select *
From (Select R1=max(RowNr),R2=max(RowNr)+1 From cte0 A where Y<@Y) A
Join (Select C1=max(ColNr),C2=max(ColNr)+1 From cte0 A where X<@X) B
on 1=1
)
,cte2 as (
Select X1 = max(case when C=1 then X end)
,X2 = max(case when C=2 then X end)
,Y1 = max(case when R=1 then Y end)
,Y2 = max(case when R=2 then Y end)
,Q11 = max(case when R=1 and C=1 then V end)
,Q12 = max(case when R=1 and C=2 then V end)
,Q21 = max(case when R=2 and C=1 then V end)
,Q22 = max(case when R=2 and C=2 then V end)
From (
Select *
,R=Dense_Rank() over (Order By RowNr)
,C=Dense_Rank() over (Order By ColNr)
From cte0 A
Cross Join cte1
Where RowNr between R1 and R2
and ColNr between C1 and C2
) A
)
Select Value = [dbo].[udf-Stat-Interpolate](@Y,Y1,Y2,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q11,Q12) ,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q21,Q22) )
From cte2
Returns
Value
1.0876
最后,如果有兴趣,UDF
CREATE Function [dbo].[udf-Stat-Interpolate] (@PosNr float,@PosMin float,@PosMax float,@ValMin float,@ValMax float)
Returns Float as
Begin
Return (((@PosNr-@PosMin)/(@PosMax-@PosMin)*(@ValMax-@ValMin)))+@ValMin
End
Edit - If matrix is stored as illustrated above (#2)
Declare @Y float = 2.5
Declare @X float = 1.6
Select Value = [dbo].[udf-Stat-Interpolate](@Y,Y1,Y2,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q11,Q12),[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q21,Q22) )
From (
Select X1 = max(case when C=1 then X end)
,X2 = max(case when C=2 then X end)
,Y1 = max(case when R=1 then Y end)
,Y2 = max(case when R=2 then Y end)
,Q11 = max(case when R=1 and C=1 then V end)
,Q12 = max(case when R=1 and C=2 then V end)
,Q21 = max(case when R=2 and C=1 then V end)
,Q22 = max(case when R=2 and C=2 then V end)
From (
Select *
,R=Dense_Rank() over (Order By RowNr)
,C=Dense_Rank() over (Order By ColNr)
From YourTable A
Cross Join (
Select *
From (Select R1=max(RowNr),R2=max(RowNr)+1 From YourTable A where Y<@Y) A
Join (Select C1=max(ColNr),C2=max(ColNr)+1 From YourTable A where X<@X) B on 1=1
) B
Where RowNr between R1 and R2
and ColNr between C1 and C2
) A
) A
我不太确定我需要什么。
我将此数据保存在 CSV 文件和 SQL 数据库中。我需要做的是能够使用 table 进行双线性插值。那么当说 d = 2.5 和 HVL = 1.6 时,解决这个问题的最佳方法是什么?我可以执行的计算只是不确定如何从 table、某种形式的 LINQ 语句中 select 适当的数字?
编辑:
对于数字 1.6 和 2.5,我需要 select 它周围的数字作为 2x2 矩阵 (Bilinear interpolation)
谢谢
1) 我取了你矩阵的一小部分,如下所示:
2) 然后我们获取您的矩阵并对其进行动态归一化(参见 cte0),它看起来像这样:
现在,为了性能起见,如果这是一个静态矩阵,我会建议您以这种方式实际存储数据。
3) 给定目标值@X 和@Y,然后我们需要确定所需的行和列(在cte1 中)。结果如下所示:
- 字段和值是所需的 Row/Column 数字
4) 在 cte2 中,我们想要获取 X/Y 范围和值,看起来像这样:
4) 最后的查询是X/Yranges/values的插值小事。我使用 UDF 只是为了方便数学计算。
我应该注意到结果已经过验证,如下图所示:
好的,代码怎么样?
我应该补充一点,我将这些部分保留为 cte,这样您就可以看到各个部分是如何协同工作的。当然,这可以进一步压缩(请参阅下面的编辑)。
Declare @YourTable Table ([y] int,[x1.5] float,[x2.0] float,[x3.0] float,[x4.0] float)
Insert Into @YourTable Values
(1,1.050,1.055,1.057,1.057)
,(2,1.080,1.089,1.097,1.098)
,(3,1.091,1.103,1.114,1.446)
Declare @XML xml = (Select * from @YourTable for XML Raw)
Declare @Y float = 2.5
Declare @X float = 1.6
;with cte0 as (
Select RowNr = Dense_Rank() over (Order By r.value('@y','float'))
,ColNr = Dense_Rank() over (Order By convert(float,replace(attr.value('local-name(.)','varchar(100)'),'x','')))
,Y = r.value('@y','float')
,X = convert(float,replace(attr.value('local-name(.)','varchar(100)'),'x',''))
,V = attr.value('.','float')
From @XML.nodes('/row') as A(r)
Cross Apply A.r.nodes('./@*') AS B(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('y') )
,cte1 as (
Select *
From (Select R1=max(RowNr),R2=max(RowNr)+1 From cte0 A where Y<@Y) A
Join (Select C1=max(ColNr),C2=max(ColNr)+1 From cte0 A where X<@X) B
on 1=1
)
,cte2 as (
Select X1 = max(case when C=1 then X end)
,X2 = max(case when C=2 then X end)
,Y1 = max(case when R=1 then Y end)
,Y2 = max(case when R=2 then Y end)
,Q11 = max(case when R=1 and C=1 then V end)
,Q12 = max(case when R=1 and C=2 then V end)
,Q21 = max(case when R=2 and C=1 then V end)
,Q22 = max(case when R=2 and C=2 then V end)
From (
Select *
,R=Dense_Rank() over (Order By RowNr)
,C=Dense_Rank() over (Order By ColNr)
From cte0 A
Cross Join cte1
Where RowNr between R1 and R2
and ColNr between C1 and C2
) A
)
Select Value = [dbo].[udf-Stat-Interpolate](@Y,Y1,Y2,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q11,Q12) ,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q21,Q22) )
From cte2
Returns
Value
1.0876
最后,如果有兴趣,UDF
CREATE Function [dbo].[udf-Stat-Interpolate] (@PosNr float,@PosMin float,@PosMax float,@ValMin float,@ValMax float)
Returns Float as
Begin
Return (((@PosNr-@PosMin)/(@PosMax-@PosMin)*(@ValMax-@ValMin)))+@ValMin
End
Edit - If matrix is stored as illustrated above (#2)
Declare @Y float = 2.5
Declare @X float = 1.6
Select Value = [dbo].[udf-Stat-Interpolate](@Y,Y1,Y2,[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q11,Q12),[dbo].[udf-Stat-Interpolate](@X,X1,X2,Q21,Q22) )
From (
Select X1 = max(case when C=1 then X end)
,X2 = max(case when C=2 then X end)
,Y1 = max(case when R=1 then Y end)
,Y2 = max(case when R=2 then Y end)
,Q11 = max(case when R=1 and C=1 then V end)
,Q12 = max(case when R=1 and C=2 then V end)
,Q21 = max(case when R=2 and C=1 then V end)
,Q22 = max(case when R=2 and C=2 then V end)
From (
Select *
,R=Dense_Rank() over (Order By RowNr)
,C=Dense_Rank() over (Order By ColNr)
From YourTable A
Cross Join (
Select *
From (Select R1=max(RowNr),R2=max(RowNr)+1 From YourTable A where Y<@Y) A
Join (Select C1=max(ColNr),C2=max(ColNr)+1 From YourTable A where X<@X) B on 1=1
) B
Where RowNr between R1 and R2
and ColNr between C1 and C2
) A
) A