日历

2008 7.6 Sun
  12345
6789101112
13141516171819
20212223242526
2728293031  
«» 2008 - 7 «»

文章搜索

日志文章

2008年01月06日 18:27:37

使用BINARY类型来做数学计算

最近需要计算,根据两次通话时小灵通所处基站的经纬度来计算间隔距离,避免出现Matrix里面,Neo那种superman拿着小灵通到处飞,那运营商就很尴尬了:-)。每天的计算量大概1500W次。于是想测试一下BINARY类型的性能。
测试如下:
create or replace package body pkg_public is
--根据两点经纬度计算距离,使用BINARY类型

FUNCTION fun_distance(longitude_A VARCHAR2,
latitude_A VARCHAR2,
longitude_B VARCHAR2,
latitude_B VARCHAR2) RETURN PLS_INTEGER IS
PLS_distance PLS_INTEGER;--it's identical to BINARY_INTEGER
PLS_longitude_a PLS_INTEGER;
PLS_latitude_a PLS_INTEGER;
PLS_longitude_b PLS_INTEGER;
PLS_latitude_b PLS_INTEGER;
BEGIN
PLS_longitude_a := longitude_A;
PLS_latitude_a := latitude_A;
PLS_longitude_b := longitude_B;
PLS_latitude_b := latitude_B;
PLS_distance := trunc(sqrt(power((longitude_a-longitude_b),2)+power((latitude_a-latitude_b),2)));
RETURN PLS_distance;
END;
--根据两点经纬度计算距离,使用NUMBER类型
FUNCTION fun_distance_2(longitude_A VARCHAR2,
latitude_A VARCHAR2,
longitude_B VARCHAR2,
latitude_B VARCHAR2) RETURN NUMBER IS
PLS_distance NUMBER;
PLS_longitude_a NUMBER;
PLS_latitude_a NUMBER;
PLS_longitude_b NUMBER;
PLS_latitude_b NUMBER;


BEGIN
PLS_longitude_a := to_number(longitude_A);
PLS_latitude_a := to_number(latitude_A);
PLS_longitude_b := to_number(longitude_B);
PLS_latitude_b := to_number(latitude_B);
PLS_distance := trunc(sqrt(power((longitude_a-longitude_b),2)+power((latitude_a-latitude_b),2)));
RETURN PLS_distance;
END;
--测试过程,分别做500万次计算
PROCEDURE pro_test IS
t1 INTEGER;
t2 INTEGER;
rlt1 PLS_INTEGER;
rlt2 NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('Here we go.');
t1 := dbms_utility.get_time;
FOR k IN 1..5000000 LOOP -- calculating with 5000000 terms
rlt1 := fun_distance(10403324,3040059,10631109,2933081);
END LOOP;
t2 := dbms_utility.get_time;

DBMS_OUTPUT.PUT_LINE('loop1 execution time:' || TO_CHAR((t2 - t1)/100));
t1 := dbms_utility.get_time;
FOR k IN 1..5000000 LOOP -- calculating with 5000000 terms
rlt2 := fun_distance_2(10403324,3040059,10631109,2933081);
END LOOP;
t2 := dbms_utility.get_time;
DBMS_OUTPUT.PUT_LINE('loop2 execution time:' || TO_CHAR((t2 - t1)/100));
END;
end pkg_public;

测试结果:
SQL> execute pkg_public.pro_test;

Here we go.
loop1 execution time:30.36
loop2 execution time:27.77

PL/SQL procedure successfully completed

结论:BINARY_DOUBLE,BINARY_FLOAT,PLS_INTEGER,BINARY_INTEGER等数据类型,在本次测试中,比NUMBER类型
领先10%左右。这主要得益于它们可以使用native hardware arithmetic instructions。更加适合于做大规模科
学计算。
另外这个简单的经纬度计算公式:
trunc(sqrt(power((longitude_a-longitude_b),2)+power((latitude_a-latitude_b),2)));
计算出成都->重庆的直线距离:251655米,大致是正确的(在google earth随意取的坐标)
但是如果要更科学的计算,则需要考虑地球并不是一个规则的球体。

Tags: 经纬度   BINARY  

类别: SQL/PLSQL |  评论(1) |  浏览(4933) |  收藏
发表评论