Ответ 1
Ну, у меня полу-ответ.
Да, это связано с третьей стороной, но вам не нужно писать ее самостоятельно: вы проверили последнее расширение на на этой странице?
Он включает в себя несколько математических функций, среди которых sqrt().
Мне нужно вычислить эвклидовое расстояние в базе данных sqlite.
Кто-нибудь знает, как вычислить квадратные корни в sqlite, помимо написания и загрузки динамической библиотеки для математических функций?
Я близок к использованию алгоритма быстрого обратного квадратного корня здесь http://en.wikipedia.org/wiki/Fast_inverse_square_root, хотя он может превратиться в больше удовольствия, чем мне нужно прямо сейчас.
И в качестве примечания, было бы здорово выяснить, как сделать власть (что является обобщенным вопросом и более чистое кодирование, чем умножение числа само по себе).
Спасибо,
Симона
Ну, у меня полу-ответ.
Да, это связано с третьей стороной, но вам не нужно писать ее самостоятельно: вы проверили последнее расширение на на этой странице?
Он включает в себя несколько математических функций, среди которых sqrt().
Предупреждение: этот ответ зависит от языка кодирования. В моем случае С#.
Пользовательские функции SQLite были для меня болью для реализации. Наконец, после долгого времени поиска я смог реализовать его в своем коде на С#. Основная функция выглядит так:
[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));
И используя в select:
SQLiteCommand com = new SQLiteCommand("select sqrt(10.42)", connection);
Вы можете скачать полный пример здесь: http://db.tt/qzeNXwso
Или, если вы хотите только просмотреть код (или пройти через все части моего кода), я вставляю ниже полный рабочий пример кода для вычисления квадратного корня в базе данных SQLite, потому что очень сложно найти какой-либо рабочий код для этого. Чтобы создать и запустить этот пример, выполните следующие 6 шагов:
Откройте App.config и замените его (без этого шага вы можете получить ошибку сборки смешанного режима):
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup useLegacyV2RuntimeActivationPolicy="true">
<supportedRuntime version="v4.0"/>
</startup>
</configuration>
Замените свой 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;
}
}
Откройте форму 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;
}
}
}
Запустите, попробуйте и наслаждайтесь.
Насколько я знаю - вы не можете сделать это, используя только основные функции.
Вот список собственных функций Основные функции и список агрегатных функций Совокупные функции.
Чтобы решить вашу проблему, вы можете написать свой собственный UDF (пользовательская функция), как показано на рисунке ЗДЕСЬ
Это приблизительное значение sqrt для чисел до 10000. Оно может быть расширено для произвольных чисел и может быть увеличено до произвольной точности по мере необходимости. Такая табличная интерполяция - это то, что происходит в большинстве быстрых реализаций:
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() похожи, и что это работает для любого целого числа - не требуется интерполяция.
((length(x)+length(x*2)+length(x*3)
+length(x*4)+length(x*5))/5.0)-1.0
Лучшая математическая голова, чем я, возможно, придумаю лучше и более плотные аппроксимации. Учитывая, что большинство функций sqrt в c используют приближения в любом случае - это довольно хорошее решение.
Это единственный способ сделать это.