如何在sqlite中计算平方根

时间:2012-10-04 16:45:07

标签: sql sqlite math

我需要在sqlite数据库中计算欧氏距离。

除了为数学函数编写和加载动态库之外,有没有人知道如何在sqlite中计算平方根?

我接近于使用http://en.wikipedia.org/wiki/Fast_inverse_square_root中的快速反平方根算法,尽管它可能会变得比我现在需要的更有趣。

作为旁注,最好弄明白如何做权力(这是一个普遍的问题,而且编码比自己乘以数字更清晰)。

谢谢,

西蒙

6 个答案:

答案 0 :(得分:6)

好吧,我有一个半答案。

是的,它涉及第三方,但您不必自己编写:您是否检查this page上的最后一个分机?

它包含几个数学函数,其中包括sqrt()。

答案 1 :(得分:6)

警告:此答案取决于编码语言。就我而言 C#

用户定义的SQLite函数对我来说很难实现。最后,经过长时间的搜索,我能够在我的C#代码中实现它。主要功能如下:

[SQLiteFunction(Arguments = 1, FuncType = FunctionType.Scalar, Name = "Sqrt")]
class Sqrt : SQLiteFunction
{
    public override object Invoke(object[] args)
    {
        return Math.Sqrt(Double.Parse(args[0].ToString()));
    }
}

自定义功能的注册:

SQLiteFunction.RegisterFunction(typeof(Sqrt));

使用选择:

SQLiteCommand com = new SQLiteCommand("select sqrt(10.42)", connection);

您可以在此处下载完整示例:http://db.tt/qzeNXwso

或者,如果你只想查看代码(或者通过代码的所有部分),我会在下面填写完整的工作示例代码来计算SQLite数据库中的平方根,因为很难找到任何有用的代码。要创建并运行此示例,请执行以下6个步骤:

  1. 创建新项目(我的名字是Sqrt)
  2. 包含对项目的SQLite引用:
    Solution Explorer - >参考文献(右键点击:添加参考) - >程序集 - 扩展 - System.Data.SQLite(check) - >行
  3. 打开 App.config 并替换为此(如果没有此步骤,您可能会出现混合模式程序集错误):

    <?xml version="1.0" encoding="utf-8" ?>
      <configuration>
          <startup useLegacyV2RuntimeActivationPolicy="true">
              <supportedRuntime version="v4.0"/>
          </startup>
      </configuration>

  4. 使用以下代码替换 Form1.Designer.cs

    namespace Sqrt
    {
     partial class Form1
     {
     /// <summary>
     /// Required designer variable.
     /// </summary>
     private System.ComponentModel.IContainer components = null;
    
     /// <summary>
     /// Clean up any resources being used.
     /// </summary>
     /// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
     protected override void Dispose(bool disposing)
     {
        if (disposing && (components != null))
        {
            components.Dispose();
        }
        base.Dispose(disposing);
     }
    
     #region Windows Form Designer generated code
    
     /// <summary>
     /// Required method for Designer support - do not modify
     /// the contents of this method with the code editor.
     /// </summary>
     private void InitializeComponent()
     {
        this.txb_Input = new System.Windows.Forms.TextBox();
        this.txb_Output = new System.Windows.Forms.TextBox();
        this.label1 = new System.Windows.Forms.Label();
        this.label2 = new System.Windows.Forms.Label();
        this.btn_Calcualte = new System.Windows.Forms.Button();
        this.SuspendLayout();
        // 
        // txb_Input
        // 
        this.txb_Input.Location = new System.Drawing.Point(131, 12);
        this.txb_Input.Name = "txb_Input";
        this.txb_Input.Size = new System.Drawing.Size(201, 20);
        this.txb_Input.TabIndex = 0;
        // 
        // txb_Output
        // 
        this.txb_Output.BackColor = System.Drawing.Color.WhiteSmoke;
        this.txb_Output.Location = new System.Drawing.Point(131, 38);
        this.txb_Output.Name = "txb_Output";
        this.txb_Output.ReadOnly = true;
        this.txb_Output.Size = new System.Drawing.Size(201, 20);
        this.txb_Output.TabIndex = 0;
        // 
        // label1
        // 
        this.label1.AutoSize = true;
        this.label1.Location = new System.Drawing.Point(12, 15);
        this.label1.Name = "label1";
        this.label1.Size = new System.Drawing.Size(31, 13);
        this.label1.TabIndex = 1;
        this.label1.Text = "Input";
        // 
        // label2
        // 
        this.label2.AutoSize = true;
        this.label2.Location = new System.Drawing.Point(12, 41);
        this.label2.Name = "label2";
        this.label2.Size = new System.Drawing.Size(39, 13);
        this.label2.TabIndex = 1;
        this.label2.Text = "Output";
        // 
        // btn_Calcualte
        // 
        this.btn_Calcualte.Location = new System.Drawing.Point(257, 64);
        this.btn_Calcualte.Name = "btn_Calcualte";
        this.btn_Calcualte.Size = new System.Drawing.Size(75, 23);
        this.btn_Calcualte.TabIndex = 2;
        this.btn_Calcualte.Text = "Calculate";
        this.btn_Calcualte.UseVisualStyleBackColor = true;
        // 
        // Form1
        // 
        this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F);
        this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
        this.ClientSize = new System.Drawing.Size(344, 98);
        this.Controls.Add(this.btn_Calcualte);
        this.Controls.Add(this.label2);
        this.Controls.Add(this.label1);
        this.Controls.Add(this.txb_Output);
        this.Controls.Add(this.txb_Input);
        this.Name = "Form1";
        this.Text = "Root square example";
        this.ResumeLayout(false);
        this.PerformLayout();
     }
     #endregion
    
     private System.Windows.Forms.TextBox txb_Input;
     private System.Windows.Forms.TextBox txb_Output;
     private System.Windows.Forms.Label label1;
     private System.Windows.Forms.Label label2;
     private System.Windows.Forms.Button btn_Calcualte;
     }
    }
    
  5. 打开Form1.cs(代码)并用以下代码替换代码:     使用系统;     使用System.Data.SQLite;     使用System.Windows.Forms;

    namespace Sqrt
    {
        // definition of custom sqlite function
        [SQLiteFunction(Arguments = 1, FuncType = FunctionType.Scalar, Name = "Sqrt")]
        class Sqrt : SQLiteFunction
        {
            public override object Invoke(object[] args)
            {
                return Math.Sqrt(Double.Parse(args[0].ToString())); // return result of math sqrt function
            }
        }
    
        public partial class Form1 : Form
        {
            public Form1()
            {
                InitializeComponent();
                this.btn_Calcualte.Click += new System.EventHandler(this.btn_Calcualte_Click);
            }
    
            private void btn_Calcualte_Click(object sender, EventArgs e)
            {
                if (txb_Input.Text.Length == 0)
                    return;
                try { SQLiteConnection.CreateFile(AppDomain.CurrentDomain.BaseDirectory + "test.s3db"); }
                catch { }
                SQLiteConnection con = new SQLiteConnection("Data Source=test.s3db");
                SQLiteFunction.RegisterFunction(typeof(Sqrt)); // register custom function
                con.Open();
                SQLiteCommand com = new SQLiteCommand("select sqrt(" + txb_Input.Text.Replace(',', '.') + ")", con); // select result
                string res = com.ExecuteScalar().ToString();
                txb_Output.Text = res;
            }
        }
    }
    
  6. 跑步,尝试和享受。

答案 2 :(得分:4)

对于10000以下的数字,这是sqrt的近似值。它可以扩展为任意数字,并且可以根据需要扩展到任意精度。这种表格插值无论如何都会在大多数快速实现中发生:

case when weight >= 1 and weight<=10 then 1+0.240253073*(weight-1) 
     when weight>=10 and weight<=100 then 3.16227766+0.075974693*(weight-10) 
     when weight>=100 and weight<=1000 then 10+0.024025307*(weight-100)      
     else 31.6227766+0.007597469 *(weight-1000) end

有一个奇怪的事实,你在这样的10平方根插值表中使用的每个因子是前一个的0.316227766倍 - 所以你可以使这个工作任意大数,甚至填充这些值的表,使其适用于任何数字。 (这会导致一些压缩吗?)

或者这个可爱的整数log10,使用长度函数(插值表可能在这里工作得更好,但我喜欢log10和length()是相似的,这适用于任何整数 - 不需要插值。< / p>

 ((length(x)+length(x*2)+length(x*3)
  +length(x*4)+length(x*5))/5.0)-1.0

比我更好的数学头可能会得出更好更密集的近似值。考虑到c中的大多数sqrt函数无论如何都使用近似值 - 这是一个非常好的解决方案。

这是唯一的本地方式。

答案 3 :(得分:2)

据我所知 - 你不能只使用核心功能。

以下是本机函数列表Core functions和聚合函数列表Aggregate functions

要解决您的问题,您可以编写自己的UDF(用户定义的函数),如图所示HERE

答案 4 :(得分:0)

<块引用>

2021-03-12 (3.35.0)

添加了内置的 SQL 数学函数()。 (需要 -DSQLITE_ENABLE_MATH_FUNCTIONS 编译时选项。)

Built-In Mathematical SQL Functions

<块引用>

sqrt(X) 返回 X 的平方根。如果 X 为负,则返回 NULL。

答案 5 :(得分:0)

仅当数学函数不可用时......而且真的只是在绝望中,因为这不会很快......

-- bisect to find the square root to any tolerance desired
with 
 input(n) as (select 500), --input
 sqrt(lo, hi, guess, n, i) as (
  select 1, n, n/2, n, 0 from input
  union all
  select case when guess*guess < n then guess else lo end,
         case when guess*guess < n then hi else guess end,
         case when guess*guess < n then (hi+guess)/2.0 else (lo+guess)/2.0 end,
         n ,
         i +1 from sqrt
         where abs(guess*guess - n) > 0.0001), -- tolerance
 sqrt_out(x, n) as (select guess, n from sqrt order by sqrt.i desc limit 1)
 select * from sqrt_out