Wednesday, December 31, 2008

神州令

神州令 征天庭

年少梦狂吞江海 初醒摆弓射日月;傲雪炎阳铸经纬 孤舟昆仑祭轩辕。

笑谈浮生千杯过 醉悯天下苍生怜;棋点江山书韬略 峥嵘岁月惘然间。

天罡封臣凌烟阁 中原六路聚英贤;东海陈兵八千万 踏云乘风诛群仙。

怒火燎原斩鬼神 九州归定霜寒剑;古今豪杰出我辈 百年山河一朝卷。

Sunday, December 28, 2008

求数组中最长递增子序列

今天睡前翻看《编程之美》,这是每晚的必读。程序与数学在这帮Microsoft的天才工程师们手中结合得通俗易懂。
当中有个题目:写一个时间复杂度尽可能低的程序,求数组最长递增子序列 的解答方式让我觉得是那么不尽人意。
原题:求一个1维数组(N个元素)中的最长递增子序列的长度。
例如 L = [1,-1,2,-3,4,-5,6,-7] 的最长子序列是 1,2,4,5.

书上的解答思路过于注重了各个元素之间相互的比较。从系统工程学来解释就是内耗过大。所以在这样的思路下,书上的最低时间复杂度为O(n*logn).

于是我干脆跳出了这样一个思路。把时间复杂度控制到了O(n).

1 取出第1个元素E1为新的序列S1,
2 取出第2个元素E2和E1做比较,如果E2>E1,则追加到S1中; 否则,把E2放到新序列S2中
3 取出第3个元素E3和所有已有序列的最后一个元素比较,判断法则如同步骤2
.......
当序列遍历完成时,程序结束。

这是一个动态规划的思想。 就拿L为例,遍历L:每个虚线之间代表一个步骤
------------------------------
1
------------------------------
1
-1
------------------------------
1,2
-1,2
------------------------------
1,2
-1,2
-3
------------------------------
1,2,4
-1,2,4
-3,4
------------------------------
1,2,4
-1,2,4
-3,4
-5
------------------------------
1,2,4,6
-1,2,4,6
-3,4,6
-5 ,6
------------------------------
1,2,4,6
-1,2,4,6
-3,4,6
-5 ,6
-7
------------------------------


遍历结束。这样就列举出了所有的递增子序列,自然最长序列一目了然。但是这样的空间消耗又大了。 那么我们可以在这个基础上优化空间。
我们观察上面的各个步骤可以发现:
如果各个序列组的最后一个元素相同,那么非最长序列就一定不可能是后结果(相关证明请参见文章末尾)
这样的话,我们重新遍历L。
------------------------------
1
------------------------------
1
-1
------------------------------
1,2
-1,2
------------------------------
1,2
-1,2
-3
------------------------------
1,2,4
-1,2,4
-3,4 该序列可删除
------------------------------
1,2,4
-1,2,4
-5
------------------------------
1,2,4,6
-1,2,4,6
-3,4,6 该序列可删除
-5 ,6 该序列可删除
------------------------------
1,2,4,6
-1,2,4,6
-5 ,6
-7
------------------------------
(完)


证明: 如果各个序列组的最后一个元素相同,那么非最长序列就一定不可能是后结果
blogspot不支持TeX公式所以这里用文字叙述。

对于S1,S2....SN满足S1.LastElement = .... = SN.LastElement
=> 当L中取出元素E作比较,
如果E>S1.LastElement,则E>Sx.LastElement, 其中x属于1......N.
如果E无论L中的元素为何值,则S1到SN之间的长度大小关系不变。
=>S1到SN中的最长序列Smax不变(注意不是长度不变,而是序号不变)。
=>如果Sx不是最长序列,则Sx必然不可能成为整个程序的最终结果。


Saturday, December 27, 2008

Python3.0 Urllib体验

首先推荐大家接触python3.0. 有争议的东西毕竟是好东西.
http://python.org/ftp/python/3.0/Python-3.0.tar.bz2 可下载python3.0 可以推荐大家玩玩. 如果担心和当前python环境影响没关系.解压后进入该目录.

sudo su
mkdir /opt/python3.0
./configure --prefix=/opt/python3.0 && make && make install
ln -s /opt/python3.0/bin/python3.0 /usr/bin/python3.0



python3.0出了之后.像我这样热衷爬虫的偏执狂最关心的就是它的urllib.
可以去python.org看看文档,urllib是修改比较剧烈的模块.urllib2和urllib被整合到了urllib包.相应的方法都被归到不同模块中. 在下面的代码中,urlopen, urlencode 被定义在request,parse模块.




#!/usr/bin/python3.0
# -*- coding:utf-8 -*-

#-------------------------------------------
# Designer : Free.Wang
# E-mail : freefis@Gmail.com
# Licence : License on GPL Licence
# Archieved : Dec 27 2008
#-------------------------------------------

from urllib import request,parse

class Makesocket:
""" Build for Make a full HttpRequest via POST/GET """
def __init__(self,loginurl,param):
# login url to recieve param , Post/Get param
self.loginurl = loginurl
self.param = param

def cookie(self):
"""make a Container for Cookie"""
self.cookies = request.HTTPCookieProcessor()
# opener will be used to open Url with cookie.
# build the cookie container.
self.opener = request.build_opener(self.cookies)
request.install_opener(self.opener)

def run(self):
""" get Response. """
# serialize the Param
# Login to Get Cookie ,Which will be Push into self.opener.
# get request with Cookie.
self.encodeparam = parse.urlencode(self.param)
request.urlopen(self.loginurl,self.encodeparam)
conn = self.opener.open("http://www.hellofreefis.com/profile/")
print(conn)

if __name__ == '__main__':
oginurl = "http://www.hellofreefis.com/info_oper.php?tag=signin&pageref="
param = {
'name':"freefis",
'pwd':"freefis' passwod"
}
conn = Makesocket(loginurl,param)
conn.cookie()
conn.run()


测试成功.Py3.0的改动还是很大的.但愿Python4.0出现的时候,不会再来革命.我个人角度对这次改动还是很肯定.感谢Guido把reduce函数保留到functools模块中.
希望各大公司和*nix操作系统发行者能尽快支持python3.0.

P.S:以上代码让我觉得很"悲剧".blogspot转义空格的支持不够到位.若要迁移代码的朋友,请自行缩进.

Opensocial和F8的博弈

这次Google hackathon的深刻印象,有来自Google名扬天下美食,还有Google 天才工程师和各大SNS平台的大牛们,还有在Shawn Shen的推荐下做了一次GAE的临时工程师.
当然最大的收获在于有一次把Idea变成了现实.EasyWrite 让我从此把庞大复杂的Gmail变成了一个简单的备忘录. 最近在看Turing Award演讲集.其中1974年的唐纳德.克努特的<计算机编程艺术>让我觉得:
最自由的程序员的就是随时把自己的idea变为现实.虽然我一直不把自己定位于一个Programmer.

Opensocial的出现是备受争议的.不管是宏观到产品发展战略,还是围观到它的设计哲学.
但不论怎样,我该关心的,就是它是否适合开发者.在这里,衡量的标准,我坚持Jobs的Easy & Useful.

简单的搜索了一下关于 OPENSOCIAL的开发讨论.不少朋友都认为开发曲线比较陡峭.特别是需要对Javascript的能力.不过,任何一个杰出的行动都要经历3个步骤:贬低,讨论,行动.无论F8,OPS.
不管怎样,自己尝试是最好的. 说说我的理解:

区别1:微观的API调用行为.
OPS(这里我们简称OpenSocial)的是基于Javascript实现API容器.而F8是基于Http请求URL. 起初我觉得单独的一个URL访问是很直接明了的.然后和Google工程师Niucl做了一下讨论.他给了我一个很简单的回答,那就是OPS封装了这些具体的请求过程.从而使用户把注意力完全集中到了API中.而且OPS提供了更为丰富的API内容. 所以问题就在于,Google是假设用户具有一定Javascript开发水平的.

区别2:宏观的设计模式.
F8是放到了服务器.而OPS则是放到了客户端.然后再发回服务器.开始我不理解OPS为什么要多这一条生产环节.目前我觉得合理的理解是1.减轻应用程序服务器负担,2.用户体验更加直接.这样来自API返回数据的处理,是先交给了javascript,当然也可以再通过Ajax发回APP-SERVER,但从效率和性能上来说,这就不言而喻了. APP本身规模和返回数据的复杂性而言,也许并不需要交给BLL层. 不管这是不是处于OPS的本意,我认为这点还是符合我对APP的定位的.因为基于SNS的APP不需要太复杂的逻辑.否则这和用自己服务器搭建一个地道的SAAS有什么区别?


还有一个我很赞同的设计理念是统一了API SDK.OPS是强制于Javascript.JS的解释环境是主流浏览器都具备的. 对于F8标准,不同语言需要不同的SDK. 比如国内某些SNS的F8-xAPI的Python SDK就是我上海的一个朋友Damien从FACEBOOK的SDK改的.而且不仅不同开发语言间切换有难度,在不同SNS的API环境中切换也是一个难度.

而F8的优势,在于直接明了.SDK通过嵌入到BLL使得开发过程更加集中,因而提高了APP代码本身的内聚性,也更传统.OPS虽然通过 JS来试图延缓生产瓶颈,但正如我刚才提到的APP的定位,或许它本身的计算强度对BLL来说轻而易举.

所以总的来说.Google和Facebook的开放平台标准之争已经形成了一个纳什均衡的博弈格局. 竞争才有进步,这是我最希望看到的.
而将来我会采取什么标准来开发,把开发成本+挑战难度+心情结合起来吧.呵呵.

其实我最关心的是Google什么时候能举办一次关于App Engine 的Hackathon. :)

[原创]OpenSocial开发模式 TDM

上周参加了 google hackthon. 才了解到这个opensocial战略.我曾经开发过国内各大SNS APP 都是基于的F8标准.所以 第一反应是,OPS(opensocial)和F8 (facebook的开放平台,目前很多SNS公司都采用)各自的优势和特点是什么.

这里很明显的区别是它们提供容器环境的方式不同.OPS是通过Javascript API,而F8是通过一个HTTP请求一个固定的URL.


应用程序展示

我的开发项目是一个igoogle的gadget.
或者在blog下方的easywrite的widget进行测试.

Opensocial doc 中有这样一句话: All OpenSocial applications are gadgets. 所以Opensocial App和gadget的开发是完全一样的----- 用固定格式的XML包装.然后把相应的前端代码装进去.


开发框架Django/Python,服务器是Google Appengine, 所以我的开发模式是基于MVC而拓展的.

我先来展示我的应用:EasyWrite.我用它来嵌入到IGOOGLE或者BLOG中. 这样当发现有好的内容时,就可以及时在当中记录,然后发送到自己的E-mail中作为收藏.

OPS首先要定义一个XML文件.它有固定的格式.然后把前端代码嵌入到其中.
我把前端代码分成了2部分------A:html. B:Javascript.

A部分代码就是一个id="show"的div标签.

B部分代码如下:
function mail() {
var url = "http://testbyfree.appspot.com/gadget/mail/";
var action = "POST";
var param = {};
param['addr'] = $('#addr').attr("value");
param['content'] = $('#content').attr("value");
request(url,param,action);
}

function response(data) {
$("#show").empty();
if (data.text.length>=5) { document.getElementById('show').innerHTML = data.text; }
else { request("http://testbyfree.appspot.com/gadget/mail/"); }
}

function request(url,cgidata,action) {
var params = {};
params[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.TEXT;
params[gadgets.io.RequestParameters.POST_DATA] = gadgets.io.encodeValues(cgidata);
params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.GET;
if (action == 'POST') { params[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST; }
gadgets.io.makeRequest(url, response, params);
}

var initurl = "http://testbyfree.appspot.com/gadget/mail/";
request(initurl);


这里我简单介绍js逻辑---
用户在提交后触发mail(),然后通过request()向APP SERVER发出请求,最后response()接到响应并输出到show的div中.
而UI的html代码(点击此处查看,GOOGLE BLOG不会转义html,所以我没列出来) 并没有写在XML中,而是放在服务器端.其实就是3个input button textarea标签.




App服务器端的python代码

# running as Django App on Google App Enging
def mail_page(request):
""" the BLL handle for Http://testbyfree.appspot.com/gadget/mail/ """
if request.POST.has_key('content'):
# this Mail API supported by GAE.
from google.appengine.api import mail
content,addr = request.POST['content'], request.POST['addr']
# the sender master be the admin of GAE APP.
message = mail.EmailMessage(
sender="freefis@gmail.com",
subject="deliver from easywrite"
)
message.to , message.body = addr , content
message.send()
return render_to_response('debug.html',{'info':"ok!","mail":"mail"})
else:
return render_to_response("mail.html")


设计模式 (Two District Mode):

以上就是这次开发的全部代码. 对于刚接触OPS的开发者来说,更关心的是javascript部分和XML部分.所以我针对这个问题,最后归纳出了这样一个开发模式:

虚线代表应答,实现代表请求。流程图有2种方式
显示区 -> JS逻辑 -> API 服务器 -> JS逻辑 -> 显示区
显示区 -> JS逻辑 -> APP服务器 -> JS逻辑 -> 显示区

橙色部分 代表XML文件包含的内容.
蓝色部分 代表服务器端.
绿色部分 代表API服务器.

我来解释一下我的设计思想:
XML文件的代码部分我分成了2个代码区:javascript区和html区. 前者包含了这个APP程序的所有javascript代码.后者就是一个简单的div标签 id="show".

一.html区.
1.服务器端显示层的HTML代码的BOBY部分可以完全原封不动的被response到div中.所以相关的设计者可以完全专注在现实层中的UI开发,不必考虑在XML中要如何设计.
2.javascript区从api-server中取得的数据,可以完全在本区中组织成相应的HTML然后返回到div中.
这样1和2的HTML设计就各自独立.不用考虑相互之间的影响.

二.javascript区
1.OPS的主要问题是对javascript的依赖,这么做可以不至于使相关代码在前端开发中过于混乱.更为关键的是集中javascript代码,使得不同代码之间的耦合松散.
2.统一了同APP服务器和API服务器的通信.明显区分了代码的功能性部分和非功能性部分.


这样一个模式的设计和F8应用程序设计的区别仅仅在于,当各开发者在后者的相关代码只需要2步:
1.把JS分离到XML文件上,2.修改相应API接口(这步对于任何开发模式都无法避免) 就可以迁移到OPS上.
这样可以旧代码迁移的成本, 而对于新的代码,可以显得思路更加清晰,分工度明细.

这就是这个相关设计模式的雏形.希望有很多朋友能够交流自己的想法.共同改进 : )



Wednesday, December 24, 2008

阅读笔记 Dec.08

近期阅读了大量的书籍.远远超过我在BIT前3年的阅读量.BETTER LATE THAN NEVER.

<分布式算法导论> <系统工程> <博弈战略学> 这三本是交换着看的.

之所以如此刻意安排, 是因为我想把计算机的思路往整个工业生产相结合. 计算机领域的很多牛人都是非本专业诞生,思考下原因,就我的接触面和体会来说,有2点:
1.兴趣, 2.更广的知识领域.
关于1的理解,我是同不少CS SE 专业的朋友讨论,感觉有不少人都迷失于本专业的前景. 为什么? 教育的引导问题? 这个我没资格讨论. 因为至今我没有上过任何一门计算机课程.
而关于2的理解, 我接触了自身的精力. 好比我自身是学习AA(Aeronautics and Astronautics)领域的,也许像我这样的CS偏执狂能从新的领域或者是视野来看待计算机工程本身领域和相关工业领域的交融.

分布式算法导论 我想将来会成为主流级书籍.毕竟这是计算机发展的未来关键.从大型计算机到小型计算机集群,再到计算机神经网络.

系统工程,则是将复杂生产归结为一个总体,然后从不同角度去细化成多个部分加以研究,按照各个目标进行权衡,全面求得最优解的方法,并使各组成部分能够最大限度地相互协调.以求取最大合作效果和最低成本.

战略博弈学则是一种大局上的思考.和系统工程的目的相同,那就是取得最优解.

同时推荐另外两本读物: 一本是<图灵奖演讲集(1966-1985)>,另一本是 <美国制宪辩论记录>.

前者是计算机界的大师级人物的经典著作. 正本书没有多少代码.,大都从数学和逻辑学,美学,系统科学去描述了计算机科学的思想精髓. 大师们的计算机本身深刻的思考和独到的理解,我相信在阅读之后, 留给我们的就是对计算机更本质学习.
当然在这个过程中,我一直专注于对计算机的学习,一是由于自己的兴趣,而是希望能够把对CS的理解延伸到整个系统工程类领域,无论在人工智能,力学体系,引信系统,还是在宏观经济学,最终到整个航空航天学领域,我想都是很有用的.

美国制宪记录我之所以有兴趣,一是因为对1787年立宪过程的那次经典辩论的着迷,二是本身这就是一个博弈的经典案例. 关于它的阅读笔记,我想在我通读完成之后,再单独写一次笔记.

Wednesday, December 17, 2008

分布式gen_server结构

在programming in Erlang中 16章最后给出了my_bank.erl的一个gen_server 实现. 当时一直在琢磨分布式的问题.把C/S分离.后来做了测试. gen_server实现的6个必要条件是 start_link , init , handle_call , handle_cast , handle_info , terminate.
换句话说,这是最基本的gen_server实现. 那么我们只需要把这6个函数放在一个执行在服务器端的模块里.
然后其他逻辑就可以转移到客户端节点了.

而客户端的主要逻辑是:
gen_server:call(Name,Request).

这样一个部署逻辑就实现了. 在具体code过程中,
server:start_link 的Name 要用 {global,arbitary_atom}.

client:gen_server:call 的Name 要用 {global,arbitary_atom}.


最后集群启动 erl -name id@domain
发送简单的 net_adm:ping(server_id@domain).
(其实server ping client 也行,但是对于伸缩性集群来说,新节点加进来的时候,当然第一行动是它发出请求,而不是server.所以这里应当养成良好习惯)

这一步的作用是建立了节点之间的通信,在完成之后,节点间会把global注册了的全局名称发布到集群中.

gen_server的分布式结构就完成了. 当我们构建一个强大多应用的服务器时,就可以把gen_server的逻辑分成N部分,然后部署到N个节点中.

这样,ERLANG的巨大威力就完美的发挥了.

Monday, December 8, 2008

Erlang Mapreduce分析

最近在研究Erlang上的MapReduce框架. 本段代码摘自<>20章 Multicores Programming.

开始----


% 代码来自phofs.erl 模块. phofs is short for Parrallel Highrt-Order Function.
-module(phofs).
-export([mapreduce/4]).

-import(lists, [foreach/2]).

%% F1(Pid, X) -> sends {Key,Val} messages to Pid
%% F2(Key, [Val], AccIn) -> AccOut


mapreduce(F1, F2, Acc0, L) ->
S = self(),
Pid = spawn(fun() -> run(S, F1, F2, Acc0, L) end),
receive
{Pid, Result} ->
Result
end.

% 本段代码的主函数 mapreduce由4个参数组成.
% F1 - Map函数
% F2 - Reduce函数
% Acc0 - 累加器的初始值, 函数最后会返回Acc0的最后累加结果
% L - 运算数据,装载在一个序列中.
run(Parent, F1, F2, Acc0, L) ->
process_flag(trap_exit, true),
ReducePid = self(),

%% 启动 Map运算
%% 对 序列L 中的每一个单元e 进行F1(e)运算. 并为每个单元创建一个进程
%% 此步是ERLANG优势的最大体现.最大化计算性能
foreach(fun(X) ->
spawn_link(fun() -> do_job(ReducePid, F1, X) end)
end, L),

% 获得 序列L 的元素量N.也就是总进程数N,并等待来自N个进程的结果,存到Dict0.
N = length(L),
Dict0 = dict:new(),
Dict1 = collect_replies(N, Dict0),

%% 启动Reduce运算,F2 代表某种Reduce 法则.用户可以自己选择并归的方案.
%% 对Dict1 哈希序列的key-value元素e 运行F2(e)并返回Acc0的累加器.
%% dict:fold函数我研究了好久,后来不断的查看文档,搜结果,讨论(可能本身愚钝:P), 其相当于lists:foldr
%% 也就是相当于python的reduce函数 e.g: reduce(lambda x,y:x+y,range(5)) ===> 1+2+3+4+5.运算集合来自Dict1,运算法则来自F2.
Acc = dict:fold(F2, Acc0, Dict1),

%% 最后把结果返回主函数mapreduce. 并打印.
Parent ! {self(), Acc}.

%% collect_replies 函数 负责处理Map进程的返回结果.并存入某个容器(这里用的是进程字典,同样,Ets,Dts都是可选容器)
%% 当某个Map 任务完成,会自动结束起进程proc,并发送'EXIT',这时候collect_replies会把这个proc 从等待进程序列删除.
>%% 当N=0时,所有map任务完毕,就会把所有相同key值的元素整合到同一个序列中作为新value,并重新对应相应的key.
%% 最后形成一个完整的 key-value Hash Table, 并返回到上面的 Dict1.

collect_replies(0, Dict) ->
Dict;
collect_replies(N, Dict) ->
receive
{Key, Val} ->
case dict:is_key(Key, Dict) of
true ->
Dict1 = dict:append(Key, Val, Dict),
collect_replies(N, Dict1);
false ->
Dict1 = dict:store(Key,[Val], Dict),
collect_replies(N, Dict1)
end;
{'EXIT', _, _} ->
collect_replies(N-1, Dict)
end.

%% Call F(Pid, X)
%% F must send {Key, Value} messsages to Pid
%% and then terminate

do_job(ReducePid, F, X) ->
F(ReducePid, X).


-----完

提示:鉴于对MapReduce函数的设计,Reduce必须等待所有相关Map进程返回才能开始启动.所以合理的配置Map-Reduce节点是关键,避免时间冗余,最小化等待时间,是M/R 架构师能力的重要体现


Wednesday, December 3, 2008

[原创]搜索引擎分词算法

最近在写www.bitok.cn的时候,一直在想方设法的优化搜索引擎的人工智能程度. 主要在中文分词上,自动分析用户的想法.

1 .比如有朋友搜索 "北京 大学". 那么SE(以后简称代替搜索引擎) 会根据 空格 把 关键字 分成 "北京"和"大学".

2. 但是如果把 空格去掉,输入 "北京大学". 那么就是一个不同的结果,精确搜索结果.

但如果要保证最大模糊度+最高精确度,这个就是难度了.

举个例子,我输入"北京大学", 我希望把 直接匹配的 "北京大学"(参见2的搜索结果) 排在前面,同时兼顾"北京" "大学"的分词,把相应模糊结果跟着搜索出来. 这个就是难点了.

参考了google算法之美. 我发现了一些方法. 比如某个关键词 "发展中国家" .

他主要的分词归类是 1."发展中"+"国家", 2. "发展"+"中国"+"家"

最普遍的方法是,根据词库,把1,2 的组合 带入到 词库(这里我们先忽略词库本身的不确定因素)中,去判断1和2所出现的概率, 最高的为最优.

-----------

但是最近闲看空气动力学的计算力学分析,其方法就是把力学问题的数学模型进行尽可能小粒度的微分,然后分析后综合.


所以我想到一个方法,就是把关键词(比如 "发展中国家" )全部按 字 来分开,比如 "发"+"展"+"中"+"国"+"家",

代入到搜索SE中用搜索,结果为 QuerySet0.

然后重新组成序列:
------------ "发展"+"展中"+"中国"+"国家"+"发展中"+"展中国"+"中国家"+"发展中国"+"展中国家".

然后带入到词库中. 假设词库足够的常用词汇统计,那么他就会把序列缩减为:
------------ "发展"+"中国"+"国家"+"发展中".

这时候再对QuerySet0分别对以上4个词进行查询,得出Query1,Query2,Query3,Query4.(每个集合中肯定有结果是重复的)

然后把Query1~4 进行整合.统计出每个结果被重复的次数.其中重复次率最高的分词结果则是最优分词结果.

(完)

Monday, December 1, 2008

django WEEKDAYS_ABBR 错误解决方案

最近在用django写学校的搜索导航.结果在ADMIN 页面 遇到了 WEEKDAYS_ABBR 未定义的情况.

这个问题是 django 0.96到1.0的 BUG. 在最新的django trunk版本就已经fix了. 所以遇到这种情况下,最彻底的方法就是重新安装最新django.

而学校最近在封外网代理. 所以我干脆直接COPY了 WEEKDAYS_ABBR .


在 django.utils.dates 中 添加:


WEEKDAYS_ABBR = {0:_('Mon'), 1:_('Tue'), 2:_('Wed'), 3:_('Thu'), 4:_('Fri'),5:_('Sat'), 6:_('Sun')}


Problem resolved.

linux matlab 2008 中文支持解决

操作系统:ubuntu 8.04
matlab版本:r2008b

matlab的GUI是用JAVA完成的。 所以基于matlab的中文问题的实质就是java环境的解决。

0.安装最新java环境 sun-java6-jre

1.复制其文件夹/usr/jvm/sun...到 $MATLABPATH/sys/java/jre/glnx86/ 并改名为jre

2.cd 进 $MATLABPATH/sys/java/jre/glnx86/jre/lib/fonts/ ,并makedir fallback

3.把 windows系统中的 WINDOWS/Fonts/simsun.ttc 复制到 fallback中

4.cd fallback && mkfontscale

5. cd .. && cat fallback/fonts.scale >> fonts.dir && chmod 666 fonts.dir

6. chmod 766 fallback/*

Followers