Crane
Table_bottom

Search
Loading
Table_bottom

分类
Table_bottom

随机文章
Table_bottom

标签云
Table_bottom

最新评论
Table_bottom

链接
Table_bottom

功能
Table_bottom

创意验证码

行走网上,不免看到好的服务,想要使用,于是第一道门槛就是注册,而且现在为了防止机器自动注册,大多采用了验证码,就此一验证码,各家是各有特色啊,一般的纯字母数字组合的不再提,而Yahoo,Google的要是碰上了的话,是个人都半天认不出来,更不要说机器了,传说这才是真正功能强大的验证码,但是人都认不出来怎么办,来个声音提示,读一遍就行了。

记得以前看到过一个新奇验证码的集合,不过不记得地方了,也没有收集下来,大概记得有个叫计算极限的比较有意思,类似这种

请输入下列式子的答案:

\lim\limits_{n\rightarrow\infty}(1+\frac{1}{n})^{n}

这样的我觉得创意已经够好了,结果今天看到一个更绝的:

验证码

这个应该还好吧,不过我刷新了一下,看这个

程序验证码

上面那个还可以用眼睛看出来,这个就得好好花一点功夫了,非geek不会玩这种东东。

一般都会跑一下这个程序来得到结果,这里有在线服务可以办到这事,强强的codepad就可以。

消失的11天

最近做一个万年历的作业,粗粗了解了下历法,做农历的时候发现农历没有固定的算法,只能查表来计算,中华人民共和国提供了1800-2100三百年间的标准农历供使用,于是一下子限制了我的程序的查询范围。所以想着公历的准确,计算的容易,可是正想着公历算法的好呢,发现了一个问题,那就是以前公历不大完善的时候,也有问题。

比如这个,在linux下打入这个命令(windows限制时间范围是1980-2099,所以看不到这个现象)

crane@debian:~$ cal 9 1752
   September 1752
Su Mo Tu We Th Fr Sa
       1  2 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29 30

cal 9 1752就是查询1752年9月的日历,于是很跌眼镜的发现,2号后面就是14号,少了11天,怎么回事呢?

查了下资料,发现是因为历法调整的问题。

1582年2月,罗马教廷要求从1582 年10月中减去10天,因此1852 年10月4日后面紧跟着就是15日。在意大利、西班牙等国家都这样处理了。其他天主教国家也很快跟着这么做了,但是新教国家不愿意修改,而且希腊等东正教 国家直到20世纪初才修改,所以这个改革在英国及其殖民地(包括美国)在1752年9月才被执行。这样 1752 年9月2日后面跟着的就是1752 年9月14日。 这就是为什么cal会生成上面输出的原因了。

这里有个问题,上面说教廷说的是减去10天,但是刚才发现1752年9月减了11天,这是为什么呢?

这是历法转换的问题,现行公历叫格里历(Gregorian calendar),这是十六世纪的罗马教皇Gregorian XIII (格里十三世)针对当时使用的儒略历 (Julian calendar)进行修订后,于1582年10月开始实行的。所以就出现了上面的1582年10月调整10天的情况。但是由于写cal的是美国人,cal是从AT&T的Unix中出来的,前面说到过,美国跟从英国的历法是从1752年才开始改的,所以不太一样,所以还牵涉了1600-1800年的一些问题。

根本原因是因为1800年以前的闰年计算的问题,我们知道闰年是4年一闰,百年不闰,400年再闰,但是1800年以前(所以不包括1800年)没百年不闰,所以就出现了偏差,比如我们可以看一下

crane@debian:~$ cal 2 1700
   February 1700
Su Mo Tu We Th Fr Sa
             1  2  3
 4  5  6  7  8  9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29

crane@debian:~$ cal 2 1600
   February 1600
Su Mo Tu We Th Fr Sa
                1  2
 3  4  5  6  7  8  9
10 11 12 13 14 15 16
17 18 19 20 21 22 23
24 25 26 27 28 29

可以清楚地看到,1600和1700年2月都是29天,一眼看去,想当然的认为多算了17天,其实实际上多算了13天,因为400,800,1200,1600是闰年,2月应该有29天。但是为什么调整的时候只少了11天呢,有个很纠结的原因,由于儒略历 (Julian calendar)公元前闰年的不规则,少算了2个闰年,从13天中去掉2天,所以在cal中看到的是少了11天。

话说回来,做万年历的时候这可是陷阱啊,得小心才是。

超级快速关机方法

最近不知什么问题,发现有时关机时停在windows正在关机那里时间比较长,而且是偶尔快偶尔慢,吃不准是什么原因,于是就想着有什么好的快速关机的方法。
首先想到的就是那个经典的操作技巧,打开任务管理器,在关机菜单中按住ctrl的同时点关闭,片刻间,机子就关了。
算算这个所费的时间,打开任务管理器(不管是任务栏右键打开还是快捷键),再选菜单,点关闭,得10秒左右吧!
程序员的话就会多想一点,这个玩意用程序怎么实现呢?那个开始菜单关机函数和任务栏的肯定不是一样的,开始菜单的比较优雅一点,提醒保存数据,通知程序退出,然后关机,而任务管理器的就相对粗暴一点,什么也不做,直接就关机,不过速度绝对一流,呵呵,我喜欢,就要这个速度。
查了下资料,一般用的是ExitWindowsEx这个函数,可能也会用InitiateSystemShutdownEx,这里交待下ExitWindowsEx的用法,查MSDN,可以看到函数原型如下:
BOOL ExitWindowsEx(
  UINT uFlags,     // shutdown operation
  DWORD dwReason   // shutdown reason
);
其中uFlags有这些选项:
EWX_LOGOFF 注销
EWX_POWEROFF 关闭系统并关闭电源
EWX_REBOOT 关机重启
EWX_SHUTDOWN  关机并指出现在可以安全关机了
还有
EWX_FORCE
EWX_FORCEIFHUNG
强制关机,可能会丢失数据。
dwReason很多,主要这么几个
SHTDN_REASON_MAJOR_APPLICATION Application issue.
SHTDN_REASON_MAJOR_HARDWARE Hardware issue.
SHTDN_REASON_MAJOR_OPERATINGSYSTEM Operating system issue.
SHTDN_REASON_MAJOR_OTHER Other issue.
SHTDN_REASON_MAJOR_POWER Power failure.
SHTDN_REASON_MAJOR_SOFTWARE Software issue.
SHTDN_REASON_MAJOR_SYSTEM System failure.
但这不是这篇文章的重点,这里要说的武器不是公开的,在MSDN中查不到,这是微软的秘密武器,ZwShutdownSystem函数,藏在ntdll.dll中。
利用ZwShutdownSystem(2)关闭电源,这个函数要求有SE_SHUTDOWN_PRIVILEGE权限,因此要先用RtlAdjustPrivilege函数来设置SE_SHUTDOWN_PRIVILEGE,SE_SHUTDOWN_PRIVILEGE的值为0x13,ZwShutdownSystem函数不通知应用程序和服务程序,就直接关闭系统了,关机速度非常快,但是如果有程序没有保存数据的话,是不会有任何提示的。
完整的程序可以这样写:

#include<stdio.h>
#include<windows.h>
#define SE_SHUTDOWN_PRIVILEGE 0x13
int main()
{
    int nRet;
    int en;
    HINSTANCE hs=NULL;
    typedef int (*SHUTDOWN)(int);
    SHUTDOWN ZwShutdownSystem;
    typedef int (*RTL_ADJUST_PRIVILEGE)(int,int,int,int *);
    RTL_ADJUST_PRIVILEGE RtlAdjustPrivilege;
    hs=LoadLibrary("ntdll.dll");
    if(hs==NULL)
  {
    MessageBox(NULL,"Cannot load DLL file!","error",MB_OK);
  }
  ZwShutdownSystem=(SHUTDOWN)GetProcAddress(hs,"ZwShutdownSystem");
  RtlAdjustPrivilege=(RTL_ADJUST_PRIVILEGE)GetProcAddress(hs,"RtlAdjustPrivilege");
    nRet=RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,TRUE,TRUE,&en);
  if(nRet==0x0C000007C)
      nRet = RtlAdjustPrivilege(SE_SHUTDOWN_PRIVILEGE,TRUE,FALSE,&en);   
  nRet=ZwShutdownSystem(2);
  FreeLibrary(hs);
  return  0;
}


编译运行,一个黑框一闪,机子就关了,像台式机拔电源一样快速。再多想一下,给它创建一个快捷方式,换个图标,然后设置为最小化运行,就看不到黑框了,再加个快捷键,这样的话,按个键,哗一下机子就黑了,光速关机啊!
弱弱的想一下,两个方法是不是本质上是一样的呢?
 

 

C语言有点变态

直接看这个程序

 

#include<stdio.h>
int f(int x)
{
        printf("%d\n",x);
}
int main(void)
{
        int (*pf)(int);
        pf=f;   //正常用法
        pf(5);
        (**pf)(5);      //这是什么
        (****************f)(5)//这个变态啊
        pf=&f;  //这个也没问题
        pf(6);
        pf=*****f;      //这是干什么
        pf(7);
        system("pause");
        return 0;
}

看着很神奇,至少有些我从来没那样写过,但是这些全部是合法的,可以编译通过。

 

VHDL编程之可逆计数器

数字逻辑学了一个学期,始终都是一堆的门元件和触发器接来接去,实在是搞得人有点晕乎,到了最后大规模集成电路的时候,终于不用(好像也不可能)那些方法了,话说coding the world不是没有道理的,这大规模的电路设计最后还是得软件来搞,可惜还没到CPLD/FPGA的地步,我们就搞了一个用VHDL做的4位(其实用VHDL 的话这个位数只是个数字而已)可逆计数器,觉得蛮有意思,代码丢在这里,万一以后想到查呢?

题目是这样的:

设计一个能清0,置数和进位输出的增1/减1的4位二进制计数器。

输入信号clr为清0端,低电平有效,信号ld为置数端,也是低电平有效,将A,B,C,D的输入值送到计数器中,并立即在Qa,Qb,Qc,Qd中输出。输入信号m为模式选择端,m=1时为加1计数,m=0时为减1计数。当cp端输入一个上升沿信号时进行一次计数,有进位/借位时qcc输出一个负脉冲。

代码如下

library ieee;
use ieee.std_logic_1164.all;
use ieee.std_logic_unsigned.all;
use ieee.std_logic_arith.all;
entity counte is
        port(cp,clr,ld,m:in std_logic;
             abcd:in std_logic_vector(3 downto 0);
               qcc:out std_logic;
                qcount:out std_logic_vector(3 downto 0));
end;
architecture count of counte is
begin
        process(cp,clr,ld)
                begin
                        if(clr='0')then
                                qcount<="0000";
                                if(m='0')then
                                        qcc<='0';
                                end if;
                        elsif(ld='0')then
                                if(abcd="0000" and m='0')then
                                        qcount<=abcd;
                                        qcc<='0';
                                elsif(abcd="1111" and m='1')then
                                        qcount<=abcd;
                                        qcc<='0';
                                else
                                        qcount<=abcd;
                                        qcc<='1';
                                end if;
                        elsif(cp'event and cp='1')then
                        if(qcount="1110" and m='1')then
                                qcount<="1111"
                                qcc<='0';
                        elsif(m='1')then
                                qcount<=qcount+1;
                                qcc<='1';
                        end if;
                        if(qcount="0001" and m='0')then
                                qcount<="0000";
                                qcc<='0';
                        elsif(m='0')then
                                qcount<=qcount-1;
                                qcc<='1';
                        end if;
                       
                        end if;
                end process;
end  count;

 

 

 

其中字母基本上和上面要求对应,就是上边的qcount对应Qa,Qb,Qc,Qd。

感觉这样的begin和end的配对,而且整个程序看起来和PASCAL还是有点像的。