Jack's Blog

流淌的心,怎能阻拦,吹来的风,又怎能阻挡。

一般程序的手动编译安装

阅读全文

由于某些安全性的原因fedora 取消了图形化界面添加su

因而只能采取后台操作添加将自己添加为su

不少freshman(包括我)都是摸索了好长时间才学会的

下面分享方法

su #输入密码后得到root权限
visudo
a #进入append模式(系统会显示INSERT)

在文件中找到这样的代码

## Allow root to run any commands anywhere
root ALL=(ALL) ALL

然后在其下面添加一行

your_name ALL=(ALL) ALLyour_name ALL=(ALL) ALL #your_name 为你的用户名

然后

按Esc 
输入“:w”(保存文件) 
输入“:q”(退出) 

FAQ

1.我的用户名在哪里可以看到?

在终端的开头[your_user_name@...]

2.在编辑文件的时候系统提示我语法错误

只要按照本操作,输入Q后便可保存并退出了

最后便可以愉快的使用sudo了

索引概论笔记

阅读全文

Before we go

16年安装了fedora 25,然而由于学校的各种事情,用windows还是比较方便。感到遗憾的是一直没有很好的利用这么好的资源,包括各种开源的软件和强大的环境友好性。

现在我想将自己的工作平台全部转移到Fedora 25上,有几大配置非常有用,我将把他们分享给大家


1.Pycharm edu

自行搜索其官网下载最新版的 pycharm edu 最新版

  1. Unpack the PyCharm Edu distribution archive that you downloaded to
     where you wish to install the program. We will refer to this destination
     location as your {installation home} below.

  2. Open a console and cd into "{installation home}/bin" and type:

       ./pycharm.sh

     to start the application. As a side effect, this will initialize various
     configuration files in the ~/.PyCharmEdu3.5 directory.

  3. [OPTIONAL] Add "{installation home}/bin" to your PATH environment
     variable so that you may start PyCharm Edu from any directory.

  4. [OPTIONAL] To adjust the value of the JVM heap size, create
      ~/.PyCharmEdu3.5/pycharm.vmoptions (or pycharm64.vmoptions
      if using a 64-bit JDK), and set the -Xms and -Xmx parameters. To see how
      to do this, you can reference the vmoptions file under
      "{installation home}/bin" as a model.

  [OPTIONAL] Changing the location of "config" and "system" directories

2.python 3

下载地址:https://www.python.org/downloads/release/python-361/

安装代码:

On Unix, Linux, BSD, macOS, and Cygwin::

    ./configure
    make
    make test
    sudo make install

3.搜狗输入法

安装fedora 中文软件源

$ sudo dnf config-manager --add-repo=http://repo.fdzh.org/FZUG/FZUG.repo 
$ sudo dnf install fzug-release -y
$ sudo dnf install sogoupinyin sogoupinyin-selinux -ysudo dnf install sogoupinyin sogoupinyin-selinux -y
$ reboot

该包已添加 fcitx-gtk2, fcitx-gtk3, fcitx-qt4 和 fcitx-qt5 模块依赖。
注意:由 iBus 切换至 Fcitx 需要 重启/注销 系统,以便 imsettings 启动相应输入法。

FAQ

使用 Sogou Pinyin

如果您使用 XDG 兼容的桌面环境,比如 KDE, GNOME, XFCE, LXDE, Cinnamon。那么当您安装好 Sogou 并重新登录后,Fcitx 和 Sogou 应该会自动启动。使用 Ctrl+Space 激活 Fcitx 便可以输入了,Shift 临时切换中英文。

1). sogou-qimpanel 未自动启动

如果 Fcitx 没有随桌面环境自动启动,请检查 imsettings 设置,正常的配置如下所示:

$ imsettings-info 
Xinput file: /etc/X11/xinit/xinput.d/fcitx.conf
GTK+ immodule: fcitx
Qt immodule: fcitx
XMODIFIERS: @im=fcitx
XIM server: /usr/bin/fcitx -D
Preferences: /usr/bin/fcitx-configtool
Auxiliary:
Short Description: FCITX
Long Description:
Icon file: /usr/share/pixmaps/fcitx.png
Is system default: TRUE
Is user default: TRUE
Is XIM server: FALSE
$ imsettings-switch fcitx  # 切换至 fcitx

如果您的桌面环境不兼容 XDG,则 sogou-qimpanel 不会自动启动。请使用桌面环境自带的自动启动工具,添加 sogou-qimpanel 启动项。

如果您的桌面环境不包含自启动工具,或您使用 startx 脚本启动图形界面,则在 ~/.profile 中添加以下命令。

$ vim ~/.profile
source /etc/sysconfig/sogoupinyin

该脚本在启动 X 时被 /etc/X11/xinit/xinitrc-common 调用,用于设置 Fcitx 环境变量,并启动 sogou-qimpanel

2). 如何安装皮肤

查看帮助信息:

$ rpm -qi sogoupinyin
皮肤保存在~/.config/sogou-qimpanel/skin/, 按以下方式安装:
  $ sudo setsebool sogou_enable_homedirs=1
  $ sogou-qimpanel Skin.ssf

3). 如何安装词库

查看帮助信息:

$ rpm -qi sogoupinyin
词库保存在~/.config/SogouPY/scd/, 按以下方式安装:
  $ sudo setsebool sogou_enable_homedirs=1
  $ sogou-qimpanel Cell.scel

4). 禁止 Sogou 访问网络

查看帮助信息:

$ rpm -qi sogoupinyin
禁止 sogou 访问网络:
  $ sudo setsebool -P sogou_access_network=0 # 默认: true

5). 小黑框问题

Xfce 桌面环境,如遇到小黑框,需开启 Compositor 功能:

Settings -> Windows Manger Tweaks -> Compositor
设置 -> 窗口管理器微调 -> 合成器

Mate 桌面环境,如遇到小黑框,需开启 Compositor 功能:

System -> Control Center -> Windows -> Enable software composit..

LXDE 桌面环境,如遇到小黑框,需要修改窗口管理器。

$ yum install compiz-lxde ccsm
$ vim ~/.config/lxsession/LXDE/desktop.conf
 window_manager=openbox  # 原参数
 window_manager=compiz-lxde-emerald  # 修改为

6). GTK/Qt 程序无法切换输入法

如果遇到无法切换输入法,则检查 Fcitx 环境变量 是否已正确设置。

$ env | grep fcitx
GTK_IM_MODULE=fcitx
QT4_IM_MODULE=fcitx
QT_IM_MODULE=fcitx
XMODIFIERS=@im=fcitx

对于兼容 XDG 的桌面环境,Fcitx 环境变量应由 imsettings 通过 /etc/X11/xinit/xinputrc 配置。

$ ll /etc/X11/xinit/xinputrc
/etc/X11/xinit/xinputrc -> /etc/alternatives/xinputrc

7). 选词框乱码

如果您碰到了 #79 的问题。可能是您启用了 "轻量界面 (fcitx-ui-light)" ,它会导致 sogou-qimpanel 不能正常显示。在 "输入法配置" -> "附加组件" 中,禁用 "轻量界面" 即可。

PS: 源里的 fcitx-cloudpinyin 可以正常使用 Google 云拼音,有了云拼音 libpinyin 之类的输入法也挺好,内存占用低。

故障排除

  • imsettings:根据 ~/.cache/imsettings/log 日志排查错误
  • Fcitx:运行 fcitx-diagnose 排查 Fcitx 错误
  • Sogou:运行 sogou-diag 收集诊断信息

参考:https://github.com/FZUG/repo/wiki/Sogou-Pinyin-%E5%B8%B8%E8%A7%81%E9%97%AE%E9%A2%98

4.安装中文软件包源

软件包列表

按 Fedora 版本浏览


Name Lisence Require repo Description
Input Methods
sogoupinyin Proprietary, GPLv2 fedora 搜狗拼音输入法
fcitx-rime GPLv3 fedora 中州韵输入法
fcitx-sunpinyin GPLv2+ fedora sunpinyin 输入法
fcitx-qt5 GPLv2 fedora fcitx qt5 输入模块
Multimedia
kwplayer GPLv3 rpmfusion 酷我音乐
doubanfm-qt MIT rpmfusion 豆瓣FM
musicbox MIT rpmfusion 网易云音乐 CLI
deepin-music-player GPLv3 rpmfusion 深度音乐
moonplayer GPLv3 rpmfusion Moonplayer播放器
simplescreenrecorder GPLv3 rpmfusion 屏幕录像
obs-studio GPLv2 rpmfusion 屏幕录像/流媒体直播
tragtor LGPLv2 rpmfusion FFmpeg音视频转码
Notes / Dict
wiznote GPLv3 fedora 为知笔记 stable
wiznote-beta GPLv3 fedora 为知笔记 beta
youdao-dict Proprietary fedora 有道词典 for linux
Browser / Proxy
opera-developer Proprietary fedora Opera developer
opera-beta Proprietary fedora Opera beta
opera-stable Proprietary fedora Opera stable
freshplayerplugin MIT fedora Firefox PPAPI flash 兼容插件
Downloads
bcloud GPLv3 fedora 百度云客户端
xware-desktop GPLv3 fedora 迅雷客户端
pointdownload GPLv3 fedora 点载, 支持迅雷/BT/ed2k下载
System tools
ccal LGPL fedora 命令行下的农历日历
grub4dos GPLv2 fedora grub 引导管理器
screenfetch GPLv3 fedora 系统信息收集
vim 7.4.764 vim fedora 编辑器之神,增加剪贴板/lua/py3支持
dkms-mt7601u GPL fedora MT7601U USB Wifi 驱动
System libraries
opencc ASL2 fedora 简繁转换库,修正依赖
sunpinyin LGPLv2 fedora 基于 SLM 模型的输入法引擎,更新字典
python-html2text GPLv3 fedora HTML -> ASCII
python3-xlib GPLv2 null Python3 X 库
python3-keybinder GPLv3 null Python3 键绑定库
python-mutagen GPLv2 fedora 处理音频元数据
python3-cairo LGPLv2 fedora Python3 cairo 绑定,修复 bug
pygobject3 LGPLv2+ fedora Python GObject 封装,修复 bug
deepin-ui GPLv3 fedora Deepin UI toolkit
deepin-utils GPLv3 fedora Deepin utils 库
deepin-gsettings GPLv3 fedora gsettings python 绑定
pyjavascriptcore GPLv3 fedora

pyjs

在我们安装完中文软件源后就可以安装很多软件,只需:

dnf install *(相应软件名称)

 

5.安装python 的依赖库

大家在运行python时,肯定不想被缺乏相应的函数库而困扰

我查阅了相应的资料,只需:

 

pip3 install turtle(for example)pip install turtle(for example)
pip install upgrade pip

pip 是Python通用的

而pip 3 是专门为python 3 开发的

6.googel chrome

cat << EOF > /etc/yum.repos.d/google-chrome.repo
[google-chrome]
name=google-chrome - \$basearch
baseurl=http://dl.google.com/linux/chrome/rpm/stable/\$basearch
enabled=1
gpgcheck=1
gpgkey=https://dl-ssl.google.com/linux/linux_signing_key.pub
EOF
dnf install google-chrome-stable
dnf install google-chrome-beta

Note for Fedora 26/25 Wayland users

If you have problems, then fallback to Xorg with modifying /etc/gdm/custom.conf file:# GDM configuration storage

[daemon]
# Uncoment the line below to force the login screen to use Xorg
WaylandEnable=false

[security]
...

Python--倒排索引

一.       实验目的

  1. 掌握列表、集合和字典的定义、赋值、使用等基本操作,熟悉处理复杂数据类型的一般流程
  2. 熟悉列表、集合和字典的常用函数和技巧
  3. 考察对文本的灵活处理和对排序算法的运用

二.       实验内容

倒排索引(Inverted index),也常被称为反向索引,是一种索引方法,用来存储某个单词存在于哪些文档之中。是信息检索系统中最常用的数据结构。通过倒排索引,可以根据单词快速获取包含这个单词的文档列表。

本实验主要完成以下三个功能:

(1). 建立索引:首先输入100行字符串,用于构建倒排索引,每行字符串由若干不含标点符号的、全部小写字母组成的单词构成,每个单词之间以空格分隔。依次读入每个单词,并组成一个由<单词, 每个单词出现的行号集合>构成的字典,其中行号从1开始计数。

(2). 打印索引:按照字母表顺序依次输出每个单词及其出现的位置,每个单词出现的位置则按行号升序输出。例如,如果“created”出现在第3, 20行,“dead”分别出现在14, 20, 22行。则输出结果如下(冒号和逗号后面都有一个空格,行号不重复):

created: 3, 20

dead: 14, 20, 22

(3). 检索:接下来输入查询(Query)字符串,每行包含一个查询,每个查询由若干关键字(Keywords)组成,每个关键字用空格分隔且全部为小写字母单词。要求输出包含全部单词行的行号(升序排列),每个查询输出一行。若某一关键字在全部行中从没出现过或没有一行字符串包含全部关键字,则输出“None”。遇到空行表示查询输入结束。如对于上面创建的索引,当查询为“created”时,输出为“3, 20”;当查询为“created dead”时,输出为“20”;当查询为“abcde dead”时,输出为“None”;

(4). 高级检索:当输入的Query以“AND:”开始,则执行“与”检索,即要求输出包含全部关键字的行;如果输入的Query以“OR:”开始,则执行“或”检索,即某行只要出现了一个关键字就满足条件。默认情况(不以“AND:”或“OR:”开始),执行“与”检索。

依次完成以上功能(提交程序命名:“学号_姓名_5.py”)


以下是代码

     #'''''Part 1 : Setup index'''  
      
    dict = {} # a emtry dictionary.  
    n = 100  
    for row in range(0,n):    
      
        information = raw_input()  
          
        line_words = information.split()   
        # split the information inputed into lines by '/n'  
      
        for word in line_words : # Judge every word in every lines .         
      
            # If the word appear first time .  
            if word not in dict :  
                item = set()   # set up a new set .  
                item.add(row+1)  # now rows  
                dict[word] = item   # Add now rows into keys(item).  
      
            # THe word have appeared before .  
            else:     
                dict[word].add(row+1)    # Add now rows into keys(item).  
      
    # print dict    we can get the information dictionary.  
      
                  
    '''''Part 2 : Print index'''   
      
    word_list = dict.items()  # Get dict's items .  
      
    word_list.sort( key = lambda items : items[0] ) # Sort by word in dict.  
      
    for word , row in word_list : # Ergodic word and row in word_list .  
          
        list_row = list(row)  
        list_row.sort()  
      
        # Change int row into string row .  
        for i in range ( 0 , len(list_row) ):  
            list_row[i] = str(list_row[i])  
          
        # print result the part 2 needed .  
        print word + ':' , ', '.join(list_row)  
      
      
    ''''' Part 3 : Query '''  
    # define judger to judger if all querys are in dict.  
    def judger(dict , query):  
        list_query = query.split()  
        for word in list_query :  
            if word not in dict :  
                return 0    # for every query ,if there is one not in dict,return 0  
        return 1   # all query in dict .  
      
    query_list = []   
      
    # for input , meet '' ,stop input.  
    while True:  
        query = raw_input()  
        if query == '' :  
            break     
        elif len(query) != 0 :  
            query_list.append(query) # append query inputed to a list query_list .  
      
      
    # Ergodic every query in query_list.       
    for list_query in query_list :  
          
        # if judger return 0.  
        if judger(dict , list_query) == 0 :  
            print 'None'  
        
        else:  
            list_query = list_query.split()  
            query_set = set()  # get a empty set  
              
            # union set to get rows .  
            for isquery in list_query :  
                query_set = query_set | dict[isquery]  
             
            # intersection to get common rows .  
            for isquery in list_query :  
                query_set = query_set & dict[isquery]  
               
            # if intersection == 0   
            if len(query_set) == 0 :  
                print 'None'  
      
            else:  
                query_result = list(query_set)  
                query_result.sort()  
                for m in range(len(query_result)) :  
                    query_result[m] = str(query_result[m])  
                  
                print ', '.join(query_result)  

for python 3

word_dic = {}
line_len = 3

# 建立索引
for i in range(line_len):
    line = input()
    words = line.split()
    for word in words:
        if word in word_dic:
            word_dic[word].add(i+1)
        else:
            word_set = set()
            word_set.add(i+1)
            word_dic[word] = word_set

#打印索引
word_list = []
for word,word_set in word_dic.items():
    word_list.append((word,word_set))

for word,line in word_list:
   list_line = list(line)
   list_line.sort()
   for i in range(len(list_line)):
    list_line[i] = str(list_line[i])

    print(word + ': ' , ', '.join(list_line))

#检索与高级索引
def judger(dict , query):
    list_query = query.split()
    for word in list_query :
        if word not in dict :
            return 0
    return 1

query_list = []
while True:
    query = input()
    if query == '' :
        break
    elif len(query) != 0 :
        query_list.append(query)

    if judger(dict , list_query) == 0 :
        print('None')
    else:
        list_query = list_query.split()
        query_set = set()  # get a empty set
        for isquery in list_query :
            query_set = query_set | dict[isquery]
        for isquery in list_query :
            query_set = query_set & dict[isquery]
        if len(query_set) == 0 :
            print('None')

        else:
            query_result = list(query_set)
            query_result.sort()
            for m in range(len(query_result)) :
                query_result[m] = str(query_result[m])

            print(', '.join(query_result))

 

打造Java集成平台

1.JAVA SE

You can download this on the oracle webside.

2. JC

 需要注意的事项

•环境变量的配置
–java_home
•jdk的安装路径,
•例如:C:\Program Files\java\jdk1.8
–classpath
•java类文件的路径
•一般配置如下:
–.;%java_home%\lib\dt.jar; %java_home%\lib\tools.jar;
–path
•命令的搜索路径
•在原来的基础上增加:%java_home%\bin

3.eclipse

自己下载就好了

【注意】本文粗体字母为矢量。

磁场看不见摸不着,又实实在在的存在着,它的本质到底是什么,往往给人有很神秘的感觉。现在主流科学界认为磁场是一种特殊的物质。

相对论认为,一个电荷相对于某一个观察者运动, 在这个观察者看来,该电荷在周围空间除产生电场外,还产生磁场,但在另外一个随电荷一同运动的观察者看来,这电荷是静止的,它周围就不存在磁场了。磁场既然是一种物质,怎么可能在一个人看来是有的,在另一个人看来是没有的?
大家想一想,自然界中有什么物质在一个人看来是有的,在另一个人看来是没有的?
有一个物体存在于空间中某个地方,一个人说它是真实存在的,一个人说它是不存在的,而且两人的说法都是正确的,这怎么可能呢?

很多人马上就说相对论是错误的,事情没有那么的简单。如果我们假定相对论是正确的,我们抓住了这种认识上的矛盾性,实际上就可以给磁场的本质做出判断。

我认为我们不应该把电磁场的本质看作是一种特殊物质,场的本质是物质相对于我们观察者运动所表现出的一种性质而不是物质本身。

举例来讲:我们眼前的一棵树、一条河是“物”,树的生长、河水的流动是“事”,这就是我们常说的事物。
物质就像一棵树、一条河,是“物”,场就像树的生长、河水的流动是“事"。
场的本质就是物质相对于我们观察者运动变化的一种表现,你把场看成是一种特殊的物质,这就是“事”和“物”不分的思想。
把场的本质看成是“事”,就像是上面所说的河水的流动,我们就很容易理解磁场相对于一个人是存在的,相对于另一个人是不存在的。
我们说一条河相对于一个人是存在的,相对于另一个人是不存在的,这肯定是荒唐的。
我们说河水的流动相对于一个人是存在的,相对于另一个人(随水流动的人)是不存在的,这肯定是有可能的。

认定场的本质就是物质相对于我们观察者运动变化的一种表现,那是什么物质在运动?

我的回答是空间!

我们只要假定:宇宙中任何一个相对于我们观察者静止的物质点周围空间都是以光速辐射式的运动,就可以解释电磁场的一切规律。

我们习惯了描述物体在空间中的运动,那我们又如何定性定量的描述空间本身的运动?

一条直线,我们可以看则是由无数个点构成,一个平面我们也可以看则是由无数个点构成,同样道理,我们可以把三维空间看则是由许多个点构成,称之为空间几何点,描述这些几何点的运动,就可以描述出空间的运动。

下面,我们来结合数学中场的定义来给出电磁场本质正确、精确的解释。

在数学中场的定义为:若空间中(或空间的某一部分),每一个点对应一个确定的量,则称这样的空间为场,当空间中每一点所对应的量为数量时,则该空间为数量场,当空间中每一个点所对应的量是一个矢量时,则称这样的空间为矢量场。

从数学中场的定义可知,场是用空间的点函数来表示的,反之,若给出空间中某一个点函数,就给出了一个场。

把场看成是运动的空间,结合数学中场的定义,我们给物理中重力场、电磁场、核力场下一个统一的定义:

相对于我们观察者,物质点周围空间中任意一个空间几何点指向该物质点的位移矢量随空间位置变化或者随时间变化,这样的空间称为物理场,也可以叫物理力场。

简单一句话,物理三大场本质就是运动变化的空间,从以上的定义可以知道,物理三大场都是矢量场。

首先我们用运动空间来定义电荷、电场:

设想一个物质点O相对于我们观测者静止,在某一个时刻,任意一个几何点P从O点出发,以光速度C【光速某些情况下可以看成矢量,用粗字体C表示矢量光速度,而标量光速用细字体C表示】沿某一个方向直线运动,射向周围无限远处空间。

从O点指向P点的矢径为R。让点O处于直角坐标系xyz的原点,矢径R是xyz和时间t的函数,随xyz的变化又随t的变化而变化,记为R = R(x,y,z,t)。

在我们观测者看来,物质点O具有正电量q是指周围有N条几何点的光速度C射向无限远处空间【负电荷是几何点从无限远处空间汇聚到电荷上的】,并且光速度C呈辐射状均匀分布。在O点周围以R的长度为半径作一个高斯包围面S,把S分割成N块,每一块面元ds上有dn条光速度C垂直穿过去。

E = k dn C/ds

上式中E就是正电场,K为比例常数。E的方向和光速度C方向一致。

也可以用把高斯面S无限分割成许多矢量面元ds我们规定指向S内侧为负,外侧为正】,用ds的方向来表示E的方向。

E = k dn C【s】/ds

s】为沿ds方向的单位矢量。

如果把n取1,式E = k dn C/ds

可以为:E = k C/△S【E】或者E = k C/△S

【E】为沿E方向的单位矢量。△S为高斯面S其中的一小块。

E = k C/△S【E】或者E = k C/△S可以称为电场的几何定义方程。

如果用【c】表示C的单位矢量,上也可以写成:

E = k C【c】/△S

由式E = k dn C/ds可以导出式E·ds =k C dn

对式E·ds = k C dn两边积分,结果为k’q=∮E·ds= k C N

K’为比例常数,∮为包围O点封闭曲面积分,q就是正电荷的电量,电荷的电量几何意义就是O点周围有N条几何点的光速C。

我们接着来给磁场下一个几何定义。

以上的点电荷O,相对于我们观察者静止,在周围空间P处产生了静电场E,当O点相对于我们观察者以速度v运动的时候,在O点周围空间P处还产生了磁场B

我们的大致思路是:O点相对于我们静止时候,周围空间以光速辐射式的运动,我们用一个高斯面S包围O点,S上一小块面积△S垂直穿过几何点的光速度C的条数反映了这个地方的电场强度E,也就是E =k C/△S。

当O点相对于我们以速度v运动,会引起v垂直方向的电场的变化,磁场的本质就是电场变化的那部分。

从实验发现,磁场B的方向和电场E方向、电荷运动速度v方向相互垂直时候,磁场最强,可以判断,BEv满足于叉乘关系。

B = a’(v ×E)

a’为常数,由于光速度CE平行,因而式B = a’(v ×E)可以写为:B = a(v ×C).

接下来我们来确定常数a的值。

B的数量应该取决于速度v和光速度C 数量的比值,还有,B描述的是空间局部性质,因而和电场一样是空间位置函数,随空间位置【这里是矢量面元ds或者高斯面S其中一小块面积△S】而变化。

可以说,B的数量应该为:B = 常数(v /C △S)

B的方向由式B = a(v×C)决定。综合两式,可以得出:

B = 常数(v ×C/ C 2△S

或者B = 常数(v ×【c】)/ C △S

这个就是磁场B 的几何定义方程。注意,以上的沿v垂直平面内分布许多条的光速度C,这样还产生沿v垂直方向许多条B,呈环绕状。所以,磁场是环绕形状的。

利用以上的电场几何定义式E = k C/△S和磁场几何定义式B = 常数(v ×C/ C2△S

很容易导出磁场B是电场E的相对论性效应:

B = v × E/ C2

薛定谔方程

上个月在网上买了三本相对论教材和一本《量子力学概论》,本打算好好研究下相对论的数学体系,可是书到了之后,我却深深地被量子力学吸引住了,不停在研读。而且在研究量子力学的同时,我的线性代数和微分方程知识也增加了不少,这确实是我没有想到的。在我看来,不管是狭义相对论还是广义相对论,它本质上都是一种几何理论,你总要想象从一个参考系观测会发生什么,然后从另外一个参考系又会看到什么;而量子力学虽然对我来讲一切都是新鲜的,但是它的数学性比较强,主要是微分方程的求解和理解。我想这也是我对量子力学更感兴趣的原因吧,因为我善于代数而不善于几何。

量子力学中让我最神往的内容莫过于费曼所发明的路径积分形式。资料记载费曼用他发明的方法在一个晚上就算出了别人几个月才算出来的结果,可见路径积分形式的优越性。当然,我也清楚,这个路径积分并不简单,它涉及到了泛函积分这一非常高深的内容,对于我这个连数学分析都还没有学好的小孩来说,泛函是难以触摸的。不过,我还是尽量想办法向它靠近。为此,我还浏览到了一些不少让人兴奋的内容,比如薛定谔的方程的推导、力学-光学类比、雅可比方程等等。

很遗憾,在正统的量子力学教材中,这些让我很兴奋的内容却鲜有涉及,有的话大多数都是一笔带过的感觉。多数量子力学不会讲到路径积分,就算有也只是作为附录。对于薛定谔方程的推导,也没有涉及到。这也让我养成了一个习惯意识:书本最有趣的东西往往都是在附录。所以对于教科书,那么写得正正式式的内容我一概没有兴趣,那些附录内容才是我最喜欢读的。可是,那些让人兴奋的内容却不一定是很难的,就像下面的薛定谔方程的启发式推导,它不仅不难,而且易于理解。

===薛定谔方程===

在量子力学诞生之前,科学家已经通过实验发现光既有波动性也有粒子性,而德布罗意提出也同时具有波动性和粒子性,这些都奠定了量子力学的基础。根据量子论,一个光子的能量可以由 

,其中 是频率,    ,h是普朗克常数,习惯记 ,即 

同时,光子也具有动量,其大小为    

,其中    

。这些性质在波和粒子之间是可以通用的,因为它们的波粒二象性。

对于最简单的一维简谐波,我们可以将它的方程写成 

。我们可以这样理解它,在   时刻,波的形状为   ,在   的位置,波幅按   规律变化。为了数学处理的方便,我们要把波改成复数形式,延伸为二维波,即   

,可见其实数部分就是一维简谐波的方程。

由于实物粒子具有波动性,那么我们就应该给粒子一个波动方程,我们以最简单的简谐波形式来考虑,即   

。下面的过程是显然的:

              

类比经典力学的,考虑保守系统,有“能量=动能+势能”,即             

。所以上式变成:

           

其中:

             

代入就得到:

                

这就是薛定谔方程,是一道线性偏微分方程。

有些敏感的读者会发现,从    

可以直接得到             

,然后代入就得到:

                 

难道这一道也是薛定谔方程的等价形式?

傅里叶变换动画.gif

当然不是,由于我们上面的是“启发式引导”,因此我们考虑的是最简单的简谐波,所以才得到不同的形式。不过由傅里叶级数的知识可以知道,再复杂的波也可以用频率不同的简谐波叠加而成,因此我们得到的方程必须满足“两个解叠加之后还是原方程的解”,也就是说,只有线性形式的薛定谔方程

                

才是正确的量子力学波动方程。说白了,就是说波动方程必须是线性的。

===总结一下===

很明显,上面只是一种形式和数学的处理,我们还没有赋予它物理意义,比如波函数的具体意义等都还没有给出,而且结果的正确性还有待检验。这并不属于严格推导,所以我强调是启发性的思考。但是量子力学教程告诉我们,这是正确的。对于量子力学入门来说,这也足够了。读者也应该清楚,这个过程并不难,甚至有点出乎意料的简单了。不过我还没有发现哪本量子力学教材提到过,它们都去缺乏这些创意性的、启发性的思考,而充满了复杂的分析计算。也许是我读的书太少了吧。又或者是每个人的学习思路都不同吧,我只是觉得,虽然不是每个人都可以学好量子力学,但每个人都可以学一些量子力学的。

转载自:http://spaces.ac.cn/archives/1799/

no title

five in row

a very interesting game:

#include <stdlib.h>
#include <stdio.h>
#include <conio.h>                                      //应用 getch() 函数 函数用途:从控制台读取一个字符,但不显示在屏幕上
#include <string.h>

//定义棋盘大小 标准 15*15棋盘
#define MAXIMUS 15

//存储对局信息 二维数组
int p[MAXIMUS][MAXIMUS];

//输出缓冲器 纵横分别 15*2+1个字符图标  15*4+3个字符图标
//目的:1、显示方形光标 2、打印棋盘(单字符长宽不等)
char buff[MAXIMUS*2+1][MAXIMUS*4+3];

//当前光标位置
int Cx,Cy;

//当前走子的玩家,1代表黑,2代表白
int Now;

//当前写入缓冲器的行数和列数位置
int wl,wp;

//在棋盘中央显示的文字信息
char* showText;

//回合数
int count;

//修改过的字符串复制函数,会忽略末端的\0
char* Copy(char* strDest,const char* strSrc);

//初始化一个对局函数
void Initialize();//Initialize:初始化

//获得棋盘中指定坐标交点位置的字符,通过制表符拼成棋盘
char* getStyle(int i,int j);

//获得指定坐标交点位置左上格的样式,通过制表符来模拟光标的显示
//getCurse:获得图案
char* getCurse(int i,int j);

//向缓冲器写入字符串
void write(char* c);

//缓冲器写入位置提行
void ln();

//将缓冲器内容输出到屏幕
void Display();

//将整个棋盘算出并储存到缓冲器,然后调用Display函数显示出来
void Print();

//在当前光标位置走子,如果非空,则返回0表示失败
int Put();

//胜负检查,即判断当前走子位置有没有造成五连珠的情况
int Check();

//进行整个对局,返回赢家信息
int RunGame();

//主函数
int main()
{
    //设置标题
    system("title 简易五子棋 ——翻转课堂");
    //设置窗口大小
    system("mode con cols=63 lines=32");
    /*设置颜色
     *system("color 0A"); 其中color后面的0是背景色代号,A是前景色代号。各颜色代码如下:
     *0=黑色 1=蓝色 2=绿色 3=湖蓝色 4=红色 5=紫色 6=黄色 7=白色 8=灰色 9=淡蓝色
     *A=淡绿色 B=淡浅绿色 C=淡红色 D=淡紫色 E=淡黄色 F=亮白色
     */
    system("color 72");
    //循环执行游戏
    while(1)
       {
         RunGame();
       }
}

//修改过的字符串复制函数,会忽略末端的\0   主要考虑到Dispaly函数
char* Copy(char* strDest,const char* strSrc)
{
    char* strDestCopy = strDest;
    while (*strSrc!='\0')
       {
            *strDest++=*strSrc++;
       }
    return strDestCopy;
}

//进行整个对局,返回赢家信息(虽然有用上)
int RunGame()
{
  //输入变量
  int input;
  //赢家信息
  int victor;
  //初始化对局
  Initialize();
  //开始无限回合的死循环,直到出现胜利跳出
  while(1)
  {
   //打印棋盘
   Print();
   //等待键盘按下一个字符
   //getch 从控制台读取一个字符,但不显示在屏幕上
   input=getch();
   //如果是ESC则退出程序,ESC的ASCLL码为27
  if(input==27)
     {
        //正常退出
        exit(0);
     }
//如果是空格则开始走子
  else if(input==0x20)
     {
//如果走子成功则判断胜负
//put判断当前位置能否走子,即是否已经走过子
       if(Put())
       {
            victor=Check();
            //轮换当前走子玩家,3-1=2,3-2=1
            Now=3-Now;
            //对局数+1
            count++;
   //如果黑方达到胜利,显示提示文字并等待一次按键,返回胜利信息
     if(victor==1)
         {
            showText="黑方获得了胜利!";
            //重新输出棋盘 且中间为showText文字
            Print();
            /*When reading a function key or an arrow key,
             *each function must be called twice;
             *the first call returns 0 or 0xE0,
             *and the second call returns the actual key code.
             */
            if(getch()==0xE0)
            {
                getch();
            }
            return Now;     //并无实际意义,只是结束循环
         }
//如果白方达到胜利,显示提示文字并等待一次按键,返回胜利信息
     else if(victor==2)
         {
            showText="白方获得了胜利!";
            Display();
            if(getch()==0xE0)
            {
                getch();
            }
            return Now;
         }
//如果回合数达到了棋盘总量,即棋盘充满,即为平局
     else if(count==MAXIMUS*MAXIMUS)
         {
            showText="平局!";
            Display();
            if(getch()==0xE0)
            {
                getch();
            }
            return 0;
         }
       }
     }
//如果按下的是方向键,会填充两次输入,第一次为0xE0表示按下的是控制键
   else if(input==0xE0)
     {
    //获得第二次输入信息
    input=getch();
    //判断方向键方向并移动光标位置
    switch(input)
         {
           case 0x4B:
           Cx--;
           break;
           case 0x48:
           Cy--;
           break;
           case 0x4D:
           Cx++;
           break;
           case 0x50:
           Cy++;
           break;
         }
//如果光标位置越界则移动到对侧
if(Cx<0)Cx=MAXIMUS-1;
if(Cy<0)Cy=MAXIMUS-1;
if(Cx>MAXIMUS-1)Cx=0;
if(Cy>MAXIMUS-1)Cy=0;
     }
   }
}

//初始化一个对局函数
void Initialize()
{
    //循环变量
    int i,j;
    //重置显示信息
    showText="";
    //回合数归零
    count=0;
    //重置对局数据
    for(i=0;i<MAXIMUS;i++)
        {
             for(j=0;j<MAXIMUS;j++)
             {
                p[i][j]=0;          //各处走子归零
             }
        }
    //重置光标到中央
    Cx=Cy=MAXIMUS/2;
    //重置当前为黑方
    Now=1;
}

//获得棋盘中指定坐标交点位置的字符,通过制表符拼成棋盘
char* getStyle(int i,int j)
{
    //1为黑子
    if(p[i][j]==1)
    return "●";
    //2为白子
    else if(p[i][j]==2)
    return "○";
    //以下为边缘棋盘样式
    else if(i==0&&j==0)
    return "┏";
    else if(i==MAXIMUS-1&&j==0)
    return "┓";
    else if(i==MAXIMUS-1&&j==MAXIMUS-1)
    return "┛";
    else if(i==0&&j==MAXIMUS-1)
    return "┗";
    else if(i==0)
    return "┠";
    else if(i==MAXIMUS-1)
    return "┨";
    else if(j==0)
    return "┯";
    else if(j==MAXIMUS-1)
    return "┷";
    //中间的空位
    return "┼";
}

//获得指定坐标交点位置左上格的样式,通过制表符来模拟光标的显示
char* getCurse(int i,int j)
{

    if(i==Cx)
       {
         if(j==Cy)
         return "┏";
         else if (j==Cy+1)
         return "┗";
       }
    else if(i==Cx+1)
       {
         if(j==Cy)
         return "┓";
         else if (j==Cy+1)
         return "┛";
       }
    //如果不在光标附近则为空
         return " ";
}

//向缓冲器写入字符串
void write(char* c)
{
    //字符串复制 (地址,地址),修改 wl、wp 处的字符为*c所指字符
    strcpy(buff[wl]+wp,c);
    //移至下一列  通过ln函数移动至下一行
    wp+=strlen(c);
}

//缓冲器写入位置 提行
void ln()
{
    //行数+1
    wl+=1;
    //列数归0
    wp=0;
}

//将缓冲器内容输出到屏幕
void Display()
{
//循环变量,中间文字信息的长度
//showText 在RunGame函数里写出
    int i,l=strlen(showText);
//算出中间文字信息居中显示所在的横坐标位置
    int Offset=MAXIMUS*2+2-l/2;
//如果位置为奇数,则移动到偶数,避免混乱
    if(Offset%2==1)
   {
      Offset--;
   }
//讲中间文字信息复制到缓冲器
//由于 没有 \0 可以顺利输出缓冲期中showText后的其余字节
    Copy(buff[MAXIMUS]+Offset,showText);
//如果中间文字长度为半角奇数,则补上空格,避免混乱
    if(l%2==1)
   {
      *(buff[MAXIMUS]+Offset+l)=0x20;   //空格的ASCLL码 为16进制 0x20
   }
//清理屏幕,准备写入
   system("cls");     //system("CLS")可以实现清屏操作。
//循环写入每一行
   for(i=0;i<MAXIMUS*2+1;i++)
   {
   printf("%s",buff[i]);    //buff[i] 在Print函数里写入
//写入完每一行需要换行
   if(i<MAXIMUS*2)
   printf("\n");
   }
}

//将整个棋盘算出并储存到缓冲器(即buff 二维字符数组,寄存各位置字符),然后调用Display函数显示出来
//Print 为 写入各位置buff字符 但并不输出 Display 显示
void Print()        //Print 之后 Display
{
//循环变量
    int i,j;
    wl=0;
    wp=0;
//写入出交点左上角的字符,因为需要打印棋盘右下角,所以可以横纵各多一次循环
for(j=0;j<=MAXIMUS;j++)                 //第j行  j为行数
   {
    for(i=0;i<=MAXIMUS;i++)             //第i列  i为列数
      {
         //写入左上角字符
         write(getCurse(i,j));          //判断i,j是否在光标位置 如果不是 getCurse函数返回“  ”填充棋盘
//如果是棋盘上下边缘则没有连接的竖线,用空格填充位置
         if(j==0||j==MAXIMUS)
           {
               if(i!=MAXIMUS)           // != 暂无特殊含义
               write("  ");             //最上 最下 各空一行
           }
//如果在棋盘中间则用竖线承接上下
         else
           {
              //左右边缘的竖线更粗
               if(i==0||i==MAXIMUS-1)
               write("┃");
          //中间的竖线
         else if(i!=MAXIMUS)
               write("│");
           }
      }
//如果是最后一次循环,则只需要处理边侧字符,交点要少一排
         if(j==MAXIMUS)
           {
               break;
           }
//提行开始打印交点内容
         ln();
      //用空位补齐位置      左侧一列 补为空
         write("  ");

//按横坐标循环正常的次数
    for(i=0;i<MAXIMUS;i++)
      {
//写入交点字符
         write(getStyle(i,j));
//如果不在最右侧则补充一个横线承接左右
         if(i!=MAXIMUS-1)
           {
              if(j==0||j==MAXIMUS-1)
                {
               //上下边缘的横线更粗
                   write("━");
                }
              else
                {
               //中间的横线
                   write("—");
                }
           }
      }
//写完一行后提行
    ln();
   }
//将缓冲器内容输出到屏幕
    Display();
}

//在当前光标位置走子,如果非空,则返回0表示失败
int Put()
{
    if(p[Cx][Cy]==0)
   {
    //改变该位置数据
    p[Cx][Cy]=Now;          //标记当前走子:走子位置写入1/2
    //返回1表示成功
    return 1;
   }
    else
   {
    return 0;
   }
}

//胜负检查,即判断当前走子位置有没有造成五连珠的情况
int Check()
{
//累计横竖正斜反斜四个方向的连续相同棋子数目
int w=1,x=1,y=1,z=1,i;
//向下检查
for(i=1;i<5;i++)if(Cy+i<MAXIMUS&&p[Cx][Cy+i]==Now)w++;else break;
//向上检查
for(i=1;i<5;i++)if(Cy-i>0&&p[Cx][Cy-i]==Now)w++;else break;
//若果达到5个则判断当前走子玩家为赢家
if(w>=5)return Now;

//向右检查
for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&p[Cx+i][Cy]==Now)x++;else break;
//向左检查
for(i=1;i<5;i++)if(Cx-i>0&&p[Cx-i][Cy]==Now)x++;else break;
//若果达到5个则判断当前走子玩家为赢家
if(x>=5)return Now;

//向右下检查
for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy+i<MAXIMUS&&p[Cx+i][Cy+i]==Now)y++;else break;
//向左上检查
for(i=1;i<5;i++)if(Cx-i>0&&Cy-i>0&&p[Cx-i][Cy-i]==Now)y++;else break;
//若果达到5个则判断当前走子玩家为赢家
if(y>=5)return Now;

//向右上检查
for(i=1;i<5;i++)if(Cx+i<MAXIMUS&&Cy-i>0&&p[Cx+i][Cy-i]==Now)z++;else break;
//向左下检查
for(i=1;i<5;i++)if(Cx-i>0&&Cy+i<MAXIMUS&&p[Cx-i][Cy+i]==Now)z++;else break;
//若果达到5个则判断当前走子玩家为赢家
if(z>=5)return Now;

//若没有检查到五连珠,则返回0表示还没有玩家达成胜利
return 0;
}