Aug
21
dim arr(3)
arr(1)=-12590
arr(2)=-20306
arr(3)=-15133
str = ""
for i = 1 to 3
str = str & chr(arr(i))
next
CreateObject("SAPI.SpVoice").Speak str
arr(1)=-12590
arr(2)=-20306
arr(3)=-15133
str = ""
for i = 1 to 3
str = str & chr(arr(i))
next
CreateObject("SAPI.SpVoice").Speak str
Aug
21
上一篇提到了,使用sdbmhash来生成64bit摘要。这个算法,是需要用在PHP里头的,但是PHP在设计的时候有点囧,用于表示任意变量的 zval 这个struct里头,有一个union是用于存放不同数据类型的,而该union中用于表示整型的变量,就只有一个long。于是很杯具地:
1. 32bit OS下面的php只支持32bit整数
2. 不支持无符号整型
那个抑郁啊,于是只好用php的bcmath这个大整数库来实现上一篇的sdbmhash算法:
大整数库是用字符串来模拟的,没有对位移的直接支持。于是刚开始的时候用 bcmul($hash, 1<<6) 之类来替代C实现中的位移;然后果断发现自己SB了,直接乘65599更合适。
当然了,由于是用字符串来模拟的,可以想象这段代码效率是很低的。但是有多低呢?在我的Ubuntu虚拟机上测试了一下,1w次对18个字符的hash需要大约2.4s,也就是说一次调用大约需要0.2~0.3ms。宿主机是windows(AMD M320, 2.1GHz),php的效率更低,大约花了3~4s。在同样的时间里,纯C实现,可以进行相同的运算10,000,000+次,效率比大约是PHP:C = 1:1000。
由于0.2~0.3ms这个数量级比较大了,于是决定把它写成一个PHP扩展。参照百度文库的这篇教程 http://wenku.baidu.com/view/044da6f8941ea76e58fa04b1.html 比较快就上手了。
最终实现的效率比是大约1:100。看来PHP的扩展开销还是很大啊。
记得前年曾经和@Sandy讨论过ASP、PHP、JSP的效率,他认为ASP和PHP在同一个数量级,和JSP差距很大(而我当初则认为PHP和JSP差距不大)。这个数据很好地证明了这一点。
最后,附上这个PHP扩展。
1. 32bit OS下面的php只支持32bit整数
2. 不支持无符号整型
那个抑郁啊,于是只好用php的bcmath这个大整数库来实现上一篇的sdbmhash算法:
function sdbmhash($str)
{
$mul = "65599"; // (1 << 6) + (1 << 16) - 1
$mod = "18446744073709551616"; // 1 << 64
$hash = "0";
for ($i = 0; $i < strlen($str); ++$i)
{
$hash = bcmod(bcmul($hash, $mul), $mod);
$hash = bcmod(bcadd($hash, ord($str{$i})), $mod);
}
return $hash;
}
{
$mul = "65599"; // (1 << 6) + (1 << 16) - 1
$mod = "18446744073709551616"; // 1 << 64
$hash = "0";
for ($i = 0; $i < strlen($str); ++$i)
{
$hash = bcmod(bcmul($hash, $mul), $mod);
$hash = bcmod(bcadd($hash, ord($str{$i})), $mod);
}
return $hash;
}
大整数库是用字符串来模拟的,没有对位移的直接支持。于是刚开始的时候用 bcmul($hash, 1<<6) 之类来替代C实现中的位移;然后果断发现自己SB了,直接乘65599更合适。
当然了,由于是用字符串来模拟的,可以想象这段代码效率是很低的。但是有多低呢?在我的Ubuntu虚拟机上测试了一下,1w次对18个字符的hash需要大约2.4s,也就是说一次调用大约需要0.2~0.3ms。宿主机是windows(AMD M320, 2.1GHz),php的效率更低,大约花了3~4s。在同样的时间里,纯C实现,可以进行相同的运算10,000,000+次,效率比大约是PHP:C = 1:1000。
由于0.2~0.3ms这个数量级比较大了,于是决定把它写成一个PHP扩展。参照百度文库的这篇教程 http://wenku.baidu.com/view/044da6f8941ea76e58fa04b1.html 比较快就上手了。
最终实现的效率比是大约1:100。看来PHP的扩展开销还是很大啊。
记得前年曾经和@Sandy讨论过ASP、PHP、JSP的效率,他认为ASP和PHP在同一个数量级,和JSP差距很大(而我当初则认为PHP和JSP差距不大)。这个数据很好地证明了这一点。
最后,附上这个PHP扩展。
下载文件 (已下载 1275 次)
Aug
21
前两天在找个摘要算法,要求很简单,冲突少,生成64bit摘要;安全性可以忽略。MD5/SHA-1是好算法,但是它们生成的摘要是128/160bit的。Qining最初提出了个算法,将MD5的128bit分成4个32bit,d[0..3],然后通过以下公式获得64bit摘要:看起来挺有模有样的,但是用0..100,000去测试,发现了3个碰撞,毕竟没有数学理论的支持,胡搞还是不行的。另外再尝试了下,把MD5的前64bit拿出来,效果倒是好,前100,000没有碰撞。只是这种做法毕竟不让人放心,于是到网上搜了一下,发现不少人有此需求,但是没有现成的算法,挺无奈的。还好,有个人一语道破天机:用个字符串hash算法就行了。
于是翻出以前的一篇日志字符串的Hash,从里头把sdbm哈希函数搞出来,测试了一下(跑了好几分钟呢),效果很赞,一亿以内的整数都没有问题,代码如下:
引用
concat(d[0] XOR d[2], d[1] XOR d[3])
于是翻出以前的一篇日志字符串的Hash,从里头把sdbm哈希函数搞出来,测试了一下(跑了好几分钟呢),效果很赞,一亿以内的整数都没有问题,代码如下:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <assert.h>
using namespace std;
typedef unsigned long long ull;
ull sdbmhash(const char *s){
ull hash = 0;
while (*s){
hash = (hash << 6) + (hash << 16) - hash + *s++;
}
return hash;
}
int main()
{
const unsigned N = 100000000;
ull *all = new(nothrow) ull[N];
assert(all != NULL);
unsigned i = 0;
char tmp[100];
for (i = 1; i <= N; ++i)
{
snprintf(tmp, 100, "%09u", i);
all[i] = sdbmhash(tmp);
if (i % (N / 20) == 0) printf("i = %u\n", i);
}
sort(all, all + N);
ull * end = unique(all, all + N);
printf("%u\n", all + N - end);
delete[] all;
return 0;
}
#include <cstdio>
#include <algorithm>
#include <assert.h>
using namespace std;
typedef unsigned long long ull;
ull sdbmhash(const char *s){
ull hash = 0;
while (*s){
hash = (hash << 6) + (hash << 16) - hash + *s++;
}
return hash;
}
int main()
{
const unsigned N = 100000000;
ull *all = new(nothrow) ull[N];
assert(all != NULL);
unsigned i = 0;
char tmp[100];
for (i = 1; i <= N; ++i)
{
snprintf(tmp, 100, "%09u", i);
all[i] = sdbmhash(tmp);
if (i % (N / 20) == 0) printf("i = %u\n", i);
}
sort(all, all + N);
ull * end = unique(all, all + N);
printf("%u\n", all + N - end);
delete[] all;
return 0;
}
Aug
12
#!/bin/bash
if [ $# -eq 0 ]; then
grep
else
/bin/grep $@ --exclude-dir=.svn
fi
exit $?
if [ $# -eq 0 ]; then
grep
else
/bin/grep $@ --exclude-dir=.svn
fi
exit $?
Aug
7
----Vista/Win7摄像头拍照、录像工具----
在系统升级到Vista/Win7以后,发现系统里没有直接利用摄像头拍照、录像的工具软件,非常郁闷。在网上找了好久,终于找到两款能用的,在此share一下~~
· Ecap for Win7 是从EEEPC中提取的,支持拍照、录像,拍照保存为bmp格式,录像保存为wmv格式,推荐默认使用这个。Win7 x86测试通过,x64应该没问题;vista应该也是兼容的。
· amcap.exe 貌似是从万用摄像头驱动中提取的,没有直接的拍照功能,可以录像,默认录成基本没压缩的avi,体积非常大。设置功能很多,可以慢慢研究。xp/vista/win7应该是通用的。
这些软件都是绿色的,直接双击就可以使用,不过推荐将Ecap For Win7.exe拷贝到C:\Windows目录下,创建一个快捷方式命名为“摄像头”,拷贝到这个目录下面,然后再打开我的电脑,就像XP一样,可以看到你的摄像头了。
注意,AppData这个目录是隐藏目录,可以直接在地址栏输入打开。或者在资源管理器中按下Alt+T,在【文件夹选项】的【查看】选项卡中找到:“显示隐藏的文件、文件夹和驱动器”。
p.s. 这几个exe没有直接经过杀毒软件,但是有发送到QQ邮箱,通过QQ邮箱的卡巴斯基附件查毒,应该是没有病毒的;如果不放心,请自行杀毒检验或干脆不要使用。
在系统升级到Vista/Win7以后,发现系统里没有直接利用摄像头拍照、录像的工具软件,非常郁闷。在网上找了好久,终于找到两款能用的,在此share一下~~
· Ecap for Win7 是从EEEPC中提取的,支持拍照、录像,拍照保存为bmp格式,录像保存为wmv格式,推荐默认使用这个。Win7 x86测试通过,x64应该没问题;vista应该也是兼容的。
· amcap.exe 貌似是从万用摄像头驱动中提取的,没有直接的拍照功能,可以录像,默认录成基本没压缩的avi,体积非常大。设置功能很多,可以慢慢研究。xp/vista/win7应该是通用的。
这些软件都是绿色的,直接双击就可以使用,不过推荐将Ecap For Win7.exe拷贝到C:\Windows目录下,创建一个快捷方式命名为“摄像头”,拷贝到这个目录下面,然后再打开我的电脑,就像XP一样,可以看到你的摄像头了。
引用
C:\Users\[你的用户名]\AppData\Roaming\Microsoft\Windows\Network Shortcuts
注意,AppData这个目录是隐藏目录,可以直接在地址栏输入打开。或者在资源管理器中按下Alt+T,在【文件夹选项】的【查看】选项卡中找到:“显示隐藏的文件、文件夹和驱动器”。
p.s. 这几个exe没有直接经过杀毒软件,但是有发送到QQ邮箱,通过QQ邮箱的卡巴斯基附件查毒,应该是没有病毒的;如果不放心,请自行杀毒检验或干脆不要使用。
下载文件 (已下载 11325 次)
Aug
6
不知道有多少人注意过标题这句话。其实完整版是:
在vista时代,用过IE7,臃肿、缓慢,让我完全没有好感。相反,XP的IE6足够简洁快速,因此即使IE7和IE8都发布了,我都还坚持使用IE6。当然我知道它很不安全,但是真正促使我抛弃IE6的导火索,是它对剪贴板完全没有限制,任何一个网站,都可以轻易地获取/设置你的剪贴板的内容。IE7/IE8也提供这个功能,不过会提示用户是否授权;Chrome/Firefox浏览器则默认禁止此功能。
从那以后我几乎再没用过IE6,同时也想看看这个个不安全特性能做到什么地步,因此写了一个脚本放在博客里头。刚开始的时候这个脚本是很邪恶的,它会随机从十个来访者中抽取一个来访者,将其剪贴板的内容读取并保存在服务器上。过了几天,的确收集到了不少东西(没有密码=。=),但是想想觉得不太厚道,损RP,于是改了改,变成现在这样,每当IE6用户来访,其剪贴板内容都会被替换成前述内容。
然后我几乎就忘了这件事情了,如果不是每个一段时间都有人来我的某个博文留言,内容就是这句话。我想,大概是某个人的剪贴板里有用的内容被我替换了,心里不爽过来烦我吧。刚开始没怎么理会,后来发得多了,见到一条删一条。再后来,心里就琢磨了,不对啊,至于给这么多人留下心理阴影么?
在不久前的某一天,顿悟:原来是那些家伙,用IE6来发广告了。然后再没犹豫过,见一条,删一条。
本以为就这么结束了,但是一次偶然,发现了更囧的情况:这句话不仅仅出现在我的博客上,还出现在其他人的博客,以及与某些博文内容有关的论坛里头……当场就在风中凌乱了…………
这句话,该改了……
引用
这是felix021的恶作剧,提醒您IE6很不安全。欢迎光临: http://www.felix021.com
在vista时代,用过IE7,臃肿、缓慢,让我完全没有好感。相反,XP的IE6足够简洁快速,因此即使IE7和IE8都发布了,我都还坚持使用IE6。当然我知道它很不安全,但是真正促使我抛弃IE6的导火索,是它对剪贴板完全没有限制,任何一个网站,都可以轻易地获取/设置你的剪贴板的内容。IE7/IE8也提供这个功能,不过会提示用户是否授权;Chrome/Firefox浏览器则默认禁止此功能。
从那以后我几乎再没用过IE6,同时也想看看这个个不安全特性能做到什么地步,因此写了一个脚本放在博客里头。刚开始的时候这个脚本是很邪恶的,它会随机从十个来访者中抽取一个来访者,将其剪贴板的内容读取并保存在服务器上。过了几天,的确收集到了不少东西(没有密码=。=),但是想想觉得不太厚道,损RP,于是改了改,变成现在这样,每当IE6用户来访,其剪贴板内容都会被替换成前述内容。
然后我几乎就忘了这件事情了,如果不是每个一段时间都有人来我的某个博文留言,内容就是这句话。我想,大概是某个人的剪贴板里有用的内容被我替换了,心里不爽过来烦我吧。刚开始没怎么理会,后来发得多了,见到一条删一条。再后来,心里就琢磨了,不对啊,至于给这么多人留下心理阴影么?
在不久前的某一天,顿悟:原来是那些家伙,用IE6来发广告了。然后再没犹豫过,见一条,删一条。
本以为就这么结束了,但是一次偶然,发现了更囧的情况:这句话不仅仅出现在我的博客上,还出现在其他人的博客,以及与某些博文内容有关的论坛里头……当场就在风中凌乱了…………
这句话,该改了……
Aug
4
参考 http://hi.baidu.com/oscarbj/blog/item/43931bfbd4de3c66034f56b6.html
修改~/.subversion/config
diff-cmd = vimdiff_for_svn
下面是代码:
修改~/.subversion/config
diff-cmd = vimdiff_for_svn
下面是代码:
#!/usr/bin/python
import sys, os
diffprogram = '/usr/bin/vimdiff'
fn_old = sys.argv[6]
fn_working_copy = sys.argv[7]
# arrange the args in the order diffprogram expects them
args = ['mydiff', '-d', fn_old, fn_working_copy]
os.execv(diffprogram, args)
import sys, os
diffprogram = '/usr/bin/vimdiff'
fn_old = sys.argv[6]
fn_working_copy = sys.argv[7]
# arrange the args in the order diffprogram expects them
args = ['mydiff', '-d', fn_old, fn_working_copy]
os.execv(diffprogram, args)
Aug
3
svn的diff很好用,但是还不够好用,因为不像vim,可以很直观地看到两个文件的区别。Google了一下,发现一个还不错的解决方案( http://erik.thauvin.net/blog/news.jsp?date=2006-02-14 ),代码在这里: http://vc.thauvin.net/svn/linux/svndiff/svndiff.sh?view=markup ,但是有点小BUG。我FIX了一下,然后增加了一个小feature,允许在命令行后面跟上 "-r REV" 来指定与最新版本比较的版本号。代码如下:
@p.s. 2010.8.4 昨天给Erik发了封邮件,今天发现他已经把我的修改更新进去了:D
#!/bin/sh
# svndiff -- svn diff with vimdiff.
#
# Written by Erik C. Thauvin (erik@thauvin.net)
# May 11, 2006
#
# Copyright (C) 2006 Erik C. Thauvin. All rights reserved.
#
# This software is provided "as is" without express or implied warranties.
#
# Permission is granted to use, copy, modify and distribute this software,
# provided this disclaimer and copyright are preserved on all copies. This
# software may not, however, be sold or distributed for profit, or included
# with other software which is sold or distributed for profit, without the
# permission of the author.
#
# $Id$
#
# Modified by felix021 (felix021@gmail.com)
# Aug 3, 2010
PROGNAME=`basename $0`
if [ $# -lt 1 ]; then
echo "Usage: $PROGNAME <file> [-r REV]"
exit;
fi
filename=$1
pid=$$
TEMP=/tmp/tmp.$pid.$filename
pv=
if [ $# -gt 3 -a $2 = "-r" ]; then
pv="-r $3"
fi
svn cat $filename $pv > $TEMP
vimdiff $TEMP $filename
rm -f $TEMP
# svndiff -- svn diff with vimdiff.
#
# Written by Erik C. Thauvin (erik@thauvin.net)
# May 11, 2006
#
# Copyright (C) 2006 Erik C. Thauvin. All rights reserved.
#
# This software is provided "as is" without express or implied warranties.
#
# Permission is granted to use, copy, modify and distribute this software,
# provided this disclaimer and copyright are preserved on all copies. This
# software may not, however, be sold or distributed for profit, or included
# with other software which is sold or distributed for profit, without the
# permission of the author.
#
# $Id$
#
# Modified by felix021 (felix021@gmail.com)
# Aug 3, 2010
PROGNAME=`basename $0`
if [ $# -lt 1 ]; then
echo "Usage: $PROGNAME <file> [-r REV]"
exit;
fi
filename=$1
pid=$$
TEMP=/tmp/tmp.$pid.$filename
pv=
if [ $# -gt 3 -a $2 = "-r" ]; then
pv="-r $3"
fi
svn cat $filename $pv > $TEMP
vimdiff $TEMP $filename
rm -f $TEMP
@p.s. 2010.8.4 昨天给Erik发了封邮件,今天发现他已经把我的修改更新进去了:D