フリーソフト

アルゴリズム

Cryptographic API(CryptoAPI、CAPI)を使ってMD5などのハッシュ値を求める

Cryptographic API(CryptoAPI、CAPI)
 http://msdn.microsoft.com/en-us/library/aa380256.aspx

//---------------------------------------------------------------------------
UnicodeString __fastcall CalcHash(UnicodeString Str)
{
  UnicodeString Result="";
  HCRYPTPROV hCryptProv = NULL;
  HCRYPTHASH hHash = NULL;

  if (!::CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, 0)) {
    if(!::CryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_NEWKEYSET)) {
      return Result;
    }
  }

  try {
    if (!::CryptCreateHash(hCryptProv, CALG_MD5, 0, 0, &hHash)) return Result;
    try {
      AnsiString TmpStr=Str;
      if (!::CryptHashData(hHash, (BYTE*)TmpStr.c_str(), (DWORD)TmpStr.Length(), 0)) return Result;
      BYTE bData[1024];
      memset(bData, 0, sizeof(bData));
      CHAR Digits[] = "0123456789abcdef";
      DWORD dwDataLen = 16;
      if (!::CryptGetHashParam(hHash, HP_HASHVAL, bData, &dwDataLen, 0)) return Result;
      Result="";
      for (DWORD i = 0; i < dwDataLen; ++i) {
        Result+=Digits[bData[i] >> 4];
        Result+=Digits[bData[i] & 0xf];
      }
    } __finally {
      if (hHash) ::CryptDestroyHash(hHash);
    }
  } __finally {
    if (hCryptProv) ::CryptReleaseContext(hCryptProv,0);
  }
  return Result;
}

[BCB] HTTP Encode

AnsiString __fastcall HTTPEncodeUTF8(const AnsiString AStr)
{
  WideString WStr=AStr;
  UTF8String UStr=UTF8Encode(AStr);

  AnsiString Result="";
  for (int i=1;i<=UStr.Length();i++) {
    byte Ch=UStr[i];
    if ((Ch>='A' && Ch<='Z') ||
        (Ch>='a' && Ch<='z') ||
        (Ch=='*') ||
        (Ch=='@') ||
        (Ch=='.') ||
        (Ch=='_') ||
        (Ch=='-')) {
      Result=Result+(char)Ch;
    } else if (Ch==' ') {
      Result=Result+"+";
    } else {
      Result=Result+"%"+AnsiString().sprintf("%.2X",Ch);
    }
  }
  return Result;
}

[BCB] バイナリサーチ(2分探索)

int __fastcall TSortedObjectList::BinSearch(int Key)
{
  if (FList->Count==0)  return -1;

  int LeftIdx=0;
  int RightIdx=FList->Count-1;

  while (LeftIdx<=RightIdx) {
    int MidIdx=(LeftIdx+RightIdx)/2;
    int MidVal=(int)FList->Items[MidIdx];
    if (MidVal==Key) return MidIdx;  //見つかった
    else if (Key>MidVal) LeftIdx=MidIdx+1;
    else RightIdx=MidIdx-1;
  }

   return -1;
}

[BCB] バイナリデータをBase64エンコードする

入力されたバイナリデータをBase64エンコードする関数です。引数Bufには入力データ列を、Lengthにはその長さを指定します。エンコードの結果はAnsiString型の文字列で返されます。

AnsiString __fastcall Encode64(Byte *Buf,int Length)
{
 char *Codes64 = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
 int Byte3=0;
 AnsiString Result="";

 for (int i=0;i<Length;i++) {
  Byte3=(Byte3<<8)+(int)Buf[i];
  if ((i+1)%3==0) {
   Result=Result+Codes64[(Byte3>>18)&0x3F];
   Result=Result+Codes64[(Byte3>>12)&0x3F];
   Result=Result+Codes64[(Byte3>>6 )&0x3F];
   Result=Result+Codes64[(Byte3  )&0x3F];

   Byte3=0;
  }
 }

 int Rest=Length%3;
 switch (Rest) {
 case 1:
  Byte3=Byte3<<4;
  Result=Result+Codes64[(Byte3>>6 )&0x3F];
  Result=Result+Codes64[(Byte3  )&0x3F];
  Result=Result+"==";
  break;
 case 2:
  Byte3=Byte3<<2;
  Result=Result+Codes64[(Byte3>>12)&0x3F];
  Result=Result+Codes64[(Byte3>>6 )&0x3F];
  Result=Result+Codes64[(Byte3  )&0x3F];
  Result=Result+"=";
  break;
 }
 return Result;
}

[BCB] 3桁ごとに数字をカンマで区切る

FormatFloat('#,##0', Value);

これだけでOK。

[Delphi] 2地点の緯度経度から方位を計算する

球面三角法を利用した方位の計算です。

uses Math;

// 引数
//  Lon1 地点1の経度(度)
//  Lat1 地点1の緯度(度)
//  Lon2 地点2の経度(度)
//  Lat2 地点2の緯度(度)
//
//   北緯は0~90度、南緯は-90~0度
//   東経は0~180度、西経は-180~0度
//
// 戻り値
//  地点1から見た地点2の方位(度)
function GetDirection(Lon1:Double; Lat1:Double; Lon2:Double; Lat2:Double):Double;
var
 Lon1Rad, Lat1Rad, Lon2Rad, Lat2Rad:Double;
 LonDiff:Double;
 X,Y:Double;
 Direction:Double;
begin
 //ラジアンに変換
 Lon1Rad := Lon1 * PI / 180;
 Lat1Rad := Lat1 * PI / 180;
 Lon2Rad := Lon2 * PI / 180;
 Lat2Rad := Lat2 * PI / 180;

 LonDiff := Lon2Rad - Lon1Rad;

 Y := Cos(Lat2Rad)*Sin(LonDiff);
 X := Cos(Lat1Rad)*Sin(Lat2Rad) - Sin(Lat1Rad)*Cos(Lat2Rad)*Cos(LonDiff);
 Direction := ArcTan2(Y, X);

 Direction:=Direction*180/PI;
 if Direction < 0 then Direction:=Direction+360;

 Result:=Direction;
end;

[Delphi] 2地点の緯度経度からその間の距離を計算する

Hubenyの簡易式を使用した方法です。

uses Math;

// 引数
//  Lon1 地点1の経度(度)
//  Lat1 地点1の緯度(度)
//  Lon2 地点2の経度(度)
//  Lat2 地点2の緯度(度)
//
//   北緯は0~90度、南緯は-90~0度
//   東経は0~180度、西経は-180~0度
//
// 戻り値
//  2地点間の距離(km)
function GetHubenyDistance(Lon1:Double; Lat1:Double; Lon2:Double; Lat2:Double):Double;
var
 Lon1Rad, Lat1Rad, Lon2Rad, Lat2Rad:Double;
 LatAveRad, LatDiff, LonDiff:Double;
 Meridian, PrimeVertical:Double;
 X,Y:Double;
begin
 //ラジアンに変換
 Lon1Rad := Lon1 * PI / 180;
 Lat1Rad := Lat1 * PI / 180;
 Lon2Rad := Lon2 * PI / 180;
 Lat2Rad := Lat2 * PI / 180;

 LatAveRad := (Lat1Rad + Lat2Rad) / 2;
 LatDiff := Lat1Rad - Lat2Rad;
 LonDiff := Lon1Rad - Lon2Rad;

 //子午線曲率半径
 Meridian := 6334834 / Sqrt(Power(1 - 0.006674*Sin(LatAveRad)*Sin(LatAveRad),3));
 //卯酉線曲率半径
 PrimeVertical := 6377397 / Sqrt(1 - 0.006674*Sin(LatAveRad)*Sin(LatAveRad));

 //ヒュベニの公式
 X := Meridian*LatDiff;
 Y := PrimeVertical*Cos(LatAveRad)*LonDiff;

 Result := Sqrt(X*X + Y*Y);
end;