这个题目是很早之前我在CSDN里看到的,乍看之下好像比较简单,当然,尽管我写ASM,但我的思路一向是用C来完成的,所以一时觉得这个程序好写。当我分析了一阵以后,脑子就乱了,这一乱,我就不敢下手了。因为传说是google的面试题,于是保存着这个题目等以后来完成。
前两天跟jailu写程序,不知道是脑子突然有点开窍还是怎么地,今天早上花了2个小时把C的demo与ASM的demo都写出来了,现在就差实践了。2006-9-9 13:31
实践证明我真的是很笨,demo程序有问题,后来改了我一下午。又写了几个版本的程序,花了一天多的时间,虽然写出来的程序效率高了很多,但也是我想了好久的了,如果是面试题的话,我想我也只能拍屁股走人,把题拿回家去慢慢想喽。
这个题目的英文原题是:Consider a function which, for a given whole number n, returns the number of ones required when writing out all numbers between 0 and n. ;For example, f(13)=6. Notice that f(1)=1. What is the next largest n such that f(n)=n? 翻译过来大体是这样:有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数。比如f(13)=6,现在f(1)=1,问下一个最大的f(n)=n的n是什么?为什么f(13)=6, 因为1,2,3,4,5,6,7,8,9,10,11,12,13.数数1的个数,正好是6.请大家写出自己的算法,并统计一些在你机器上计算出1111111110的时间。语言不限,随便了。
我根据两个情况写个两种程序:一:针对单个用户输入计算0到N的1出现的个数。二:应题目要求,只计算到1111111110的所有符合情况的数字并输出。 这两个程序在各自的领域工作地很好,但算法不一样,如果互换算法的话,效率极其低下。
这里感谢一下jailu的提醒,否则我就差点要放弃ASM了,他跟我说:f(n)=f(n-1)+F(n),我才明白,我不可以把前面一个算法应用到第二个算法上去,从而做了无数的无用功。
因为是随手的程序,所以写法上很不严谨,程序很脆弱,很不好意思,呵呵。
以下是第一个算法:图形界面,计算单个值。因为有针对某些数如1000等做特别处理,所以某些大数的计算反而非常地迅速。数值的计算时间不定,但好像一般在10秒内完成统计。第一行输出信息显示统计结果,第二行输出信息显示计算时间。 又因为只使用了DD是32位的,就是说,如果输入的数字大于2147483647(2^31),会导致程序崩溃。但这个数已经足够大到算到1111111110这个最大值了。
主程序ex.asm:
.586
.model flat,stdcall
option casemap:none
include windows.inc
include user32.inc
include kernel32.inc
include shell32.inc
include masm32.inc
includelib user32.lib
includelib kernel32.lib
includelib shell32.lib
includelib masm32.lib
include C:masm32macrosMACROS.ASM
DLG_MAIN equ 1000
.const
xten dd 1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000
.data
fmt_num db " %d ",0
.data?
hInstance dd ?
hWinMain dd ?
tmpstr db 128 dup (?)
x dd ?
time dd ?
.code
_fun proc @x
LOCAL @sum
mov ecx,@x
.if ecx > 0
mov eax,ecx
shl ecx,1
shl ecx,1
mov edx,xten[ecx]
mov @sum,edx
dec eax
invoke _fun,eax
mul xten[04h]
add eax,@sum
ret
.endif
mov eax,1
ret
_fun endp
_c proc @z
LOCAL @sum,@s,@y,@xten,@x
push x
pop @x
mov eax,@z
.if eax == 0
ret
.elseif eax < 10
mov eax,1
ret
.endif
@@: mov edx,@x
shl edx,1
shl edx,1
mov ecx,xten[edx]
mov @xten,ecx
dec @x
xor edx,edx
mov @sum,edx
mov eax,@z
div ecx
mov @s,eax ;商
mov @y,edx ;余数
.if eax == 0
jmp @B
.elseif eax == 1
mov @sum,edx
inc @sum
invoke _c,edx
add @sum,eax
dec @xten
invoke _fun,@x
add eax,@sum
ret
.else
xor edx,edx
mov ecx,@xten
mul ecx
dec eax
inc @x
invoke _c,eax
mov @sum,eax
invoke _c,@y
add eax,@sum
ret
.endif
ret
_c endp
_main proc
pushad
push 9
pop x
invoke GetTickCount
mov time,eax
invoke GetDlgItemInt,hWinMain,4211,NULL,TRUE
invoke _c,eax
invoke SetDlgItemInt,hWinMain,4212,eax,TRUE
invoke GetTickCount
sub eax,time
invoke SetDlgItemInt,hWinMain,4213,eax,TRUE
popad
ret
push eax
pushad
invoke wsprintf,addr tmpstr,addr fmt_num,eax
invoke MessageBox,hWinMain,addr tmpstr,NULL,MB_OK
popad
pop eax
_main endp
_ProcDlgMain proc uses ebx edi esi hWnd,wMsg,wParam,lParam
LOCAL @szBuffer[256]:byte
mov eax,wMsg
.if eax == WM_CLOSE
invoke EndDialog,hWnd,NULL
.elseif eax == WM_INITDIALOG
push hWnd
pop hWinMain
.elseif eax == WM_COMMAND
mov eax,wParam
movzx eax,ax
.if eax == IDOK
invoke _main
.endif
.else
mov eax,FALSE
ret
.endif
mov eax,TRUE
ret
_ProcDlgMain endp
start:
invoke GetModuleHandle,NULL
mov hInstance,eax
invoke DialogBoxParam,hInstance,DLG_MAIN,NULL,offset _ProcDlgMain,NULL
invoke ExitProcess,NULL
end start
主界面:ex.rc
#include <C:masm32include esource.h>
#define DLG_MAIN 1000
DLG_MAIN DIALOG 190, 130,145,56
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU |WS_MINIMIZEBOX
CAPTION "练手程序"
FONT 10, "宋体"
...{
GROUPBOX "请输入数字",-1,2,5,138,24
EDITTEXT 4211, 10,14, 44, 11,ES_NUMBER | ES_RIGHT
ltext " ",4212,6,32,140,12
ltext " ",4213,6,42,140,12
DEFPUSHBUTTON "判断(&C)",IDOK,61,12,36,14
}
第二种算法:先是采用jailu说的穷举算法,后来经过一步步的改进,形成现在的情况,比最原始的穷举算法,速度提高了1分多钟,采用字符界面输出。 现在就是奇怪的是,竟然传递参数到堆栈反而比使用寄存器快?!
主程序ex.asm
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
![](https://i-blog.csdnimg.cn/blog_migrate/6810355c2f78c12e91b7997a8e8c583a.gif)
以下是一些输出信息:
12:27 2006-9-10:采用了有针对性的跳步算法,程序速度又提高了不少,哇哈哈。
原理是根据个位数如果为1且整个数也只有个位数为1,往前跳8,因为接下来的9个数f(n)=X,f(n+1)=X,…f(n+8)=X,既然是一样的,那就
跳过,不用算了,0~100,少测了72次,以些类推,时间节省。当然,同时因为增加了判断,所以时间上也有消耗,两者折和,时间上还是有节
省,所以我就改进了算法,结果果然时间上大有提高,算到最大数,比原来的算法快了50秒左右!
以下摘录一些结果:0--260001
f(0)=0 耗时 0 ms.
f(1)=1 耗时 0 ms.
f(199981)=199981 耗时 30 ms...
f(199984)=199984 耗时 40 ms.........
f(1599981)=1599981 耗时 310 ms...
f(1599984)=1599984 耗时 320 ms...
f(1599987)=1599987 耗时 330 ms....
f(2600000)=2600000 耗时 560 ms.
f(2600001)=2600001 耗时 560 ms.
任务结束,共耗时 570 ms .
----以下是运行到最大数的结果:(部分结果根据时间不同)
f(0)=0 0 ms.
f(1)=1 0 ms.
f(199981)=199981 30 ms.
f(199982)=199982 40 ms.
f(199983)=199983 50 ms..
f(199985)=199985 60 ms.
f(199986)=199986 70 ms..
f(199988)=199988 80 ms.
f(199989)=199989 90 ms.
f(199990)=199990 100 ms.
f(200001)=200001 110 ms.
f(1599981)=1599981 381 ms.
f(1599982)=1599982 391 ms.
f(1599983)=1599983 401 ms..
f(1599985)=1599985 411 ms.
f(1599986)=1599986 421 ms..
f(1599988)=1599988 431 ms.
f(1599989)=1599989 441 ms..
f(2600000)=2600000 671 ms.
f(2600001)=2600001 681 ms.
f(13199998)=13199998 3155 ms.
f(35000000)=35000000 8582 ms..
f(35199981)=35199981 8643 ms..
f(35199983)=35199983 8653 ms.
f(35199984)=35199984 8663 ms..
f(35199986)=35199986 8683 ms...
f(35199989)=35199989 8703 ms.....
f(117463825)=117463825 30524 ms.
f(500000000)=500000000 141434 ms.........................
f(502600000)=502600000 142205 ms..
f(513199998)=513199998 145239 ms.
f(535000000)=535000000 151448 ms.
f(535000001)=535000001 151448 ms...
f(535199984)=535199984 151518 ms.....
f(535199989)=535199989 151528 ms...
f(535200001)=535200001 151528 ms.
f(1111111110)=1111111110 349623 ms.
任务结束,共耗时 349623 ms .