分类
TeX

TeX家族

TeX家族

TeX:「强迫症」的排版引擎

TeX 是高德纳(Donald Ervin Knuth,1938年1月10日 –)教授愤世嫉俗追求完美做出来的排版引擎,同时也是该引擎使用的标记语言(Markup Language)的名称。这里所谓的引擎,是指能够实现断行、分页等操作的程序(请注意这并不是定义);这里的标记语言,是指一种将控制命令和文本结合起来的格式,它的主体是其中的文本而控制命令则实现一些特殊效果(同样请注意这并不是定义)。

LaTeX:基于TeX的排版系统

LaTeX 则是 L. Lamport (1941年2月7日 — ) 教授开发的基于 TeX 的排版系统。实际上 LaTeX 利用 TeX 的控制命令,定义了许多新的控制命令并封装成一个可执行文件。这个可执行文件会去解释 LaTeX 新定义的命令成为 TeX 的控制命令,并最终交由 TeX 引擎进行排版。

实际上,LaTeX 是基于一个叫做 plain TeX 的格式的。plain TeX 是高德纳教授为了方便用户,自己基于原始的 TeX 定义的格式,但实际上 plain TeX 的命令仍然十分晦涩。至于原始的 TeX 直接使用的人就更少了,因此 plain TeX 格式逐渐就成为了 TeX 格式的同义词,尽管他们事实上是不同的。

因此在 TeX – LaTeX 组合中,

  1. 最终进行断行、分页等操作的,是 TeX 引擎;
  2. LaTeX 实际上是一个工具,它将用户按照它的格式编写的文档解释成 TeX 引擎能理解的形式并交付给 TeX 引擎处理,再将最终结果返回给用户。

pdfTeX:TeX的引擎扩展

TeX 系统生成的文件是 dvi 格式,虽然可以用其他程序将其转换为例如 pdf 等更为常见的格式,但是毕竟不方便。

dvi 格式是为了排版而产生的,它本身并不支持所谓的「交叉引用」,pdfTeX 直接输出 pdf 格式的文档,这也是 pdfTeX 相对 TeX 进步(易用性方面)的地方。

为了解决这个问题,Hàn Thế Thành 博士在他的博士论文中提出了 pdfTeX 这个对 TeX 引擎的扩展。二者最主要的差别就是 pdfTeX 直接输出 pdf 格式文档,而 TeX 引擎则输出 dvi 格式的文档。

pdfTeX 的信息可以查看wiki.

pdfLaTeX 这个程序的主要工作依旧是将 LaTeX 格式的文档进行解释,不过此次是将解释之后的结果交付给 pdfTeX 引擎处理。

XeTeX:支持中文字符的排版引擎

高德纳教授在实现 TeX 的当初并没有考虑到中日韩等字符的处理,而只支持 ASCII 字符。这并不是说中日韩字符就无法使用 TeX 引擎排版了,事实上 TeX 将每个字符用一个框包括起来(这被称为盒子)然后将一个个的盒子按照一定规则排列起来,因而 TeX 的算法理论上适用于任何字符。ASCII 字符简单理解,就是在半角模式下你的键盘能直接输出的字符。

在 XeTeX 出现之前,为了能让 TeX 系统排版中文,国人曾使用了 天元、CCT、CJK 等手段处理中文。其中 天元和CCT 现在已经基本不用,CJK 因为使用时间长且效果相对较好,现在还有人使用。

不同于 CJK 等方式使用 TeX 和 pdfTeX 这两个不直接支持 Unicode 字符的引擎,XeTeX 引擎直接支持 Unicode 字符。也就是说现在不使用 CJK 也能排版中日韩文的文档了,并且这种方式要比之前的方式更加优秀。

XeLaTeX 和 XeTeX 的关系与 pdfLaTeX 和 pdfTeX 的关系类似,这里不再赘述。

使用 XeTeX 引擎需要使用 UTF-8 编码。

所谓编码就是字符在计算机储存时候的对应关系。例如,假设有一种编码,将汉字「你」对应为数字「1」;「好」对应为数字「2」,则含有「你好」的纯文本文件,在计算机中储存为「12」(读取文件的时候,将「12」再转换为「你好」显示在屏幕上或打印出来)。

UTF-8 编码是 Unicode 编码的一种,可以参考它的 wiki.

CTeX – MiKTeX – TeX Live:发行版软件

之前介绍了 TeX, LaTeX, pdfTeX, pdfLaTeX, XeTeX, XeLaTeX, LuaTeX 等,他们都是 TeX 家族的一部分。但是作为一个能够使用的 TeX 系统,仅仅有他们还是不够的。CTeX, MiKTeX, TeX Live 都是被称为「发行」的软件合集。他们包括了上述各种引擎的可执行程序,以及一些文档类、模板、字体文件、辅助程序等等。其中 CTeX 是建立在 MiKTeX 的基础之上的。

总结

TeX – pdfTeX – XeTeX – LuaTeX 都是排版引擎,按照先进程度递增(LuaTeX 尚未完善)。

LaTeX 是一种格式,基于 TeX 格式定义了很多更方便使用的控制命令。上述四个引擎都有对应的程序将 LaTeX 格式解释成引擎能处理的内容。

CTeX, MiKTeX, TeX Live 都是 TeX 的发行,他们是许许多多东西的集合。

分类
Linux Web

Ubuntu 查看端口占用

Ubuntu 查看端口占用

1 查看服务端口

1.1 查看已经连接的服务端口(ESTABLISHED):

$ netstat -a

1.2 查看所有的服务端口(LISTEN,ESTABLISHED):

$ netstat -ap

2 查看指定端口

查看指定端口,可以结合grep命令:

$ netstat -ap | grep 8080        

也可以使用lsof命令:

$ lsof -i:8080

3 关闭端口使用

若要关闭使用这个端口的程序,使用kill + 对应的pid::

$ kill -9 [PID]

ps:kill就是给某个进程id发送了一个信号。默认发送的信号是SIGTERM,而kill -9发送的信号是SIGKILL,即exit。exit信号不会被系统阻塞,所以kill -9能顺利杀掉进程。

注:此命令在CentOS下同样适用。

分类
Docker Linux Server Web

Ubuntu18.04服务器部署Docker

Ubuntu18.04服务器部署Docker

1.更新包索引

$ sudo apt-get updata

2.安装必要包(curl等)

$ sudo apt-get install \
    apt-transport-https \
    ca-certificates \
    curl \
    gnupg-agent \
    software-properties-common

3.添加Docker官方GPG Key

$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add -

确认一下指纹:

$ sudo apt-key fingerprint 0EBFCD88

pub   rsa4096 2017-02-22 [SCEA]
      9DC8 5822 9FC7 DD38 854A  E2D8 8D81 803C 0EBF CD88
uid           [ unknown] Docker Release (CE deb) <docker@docker.com>
sub   rsa4096 2017-02-22 [S]

4.针对x84_64系统安装最新稳定版本:

$ sudo add-apt-repository \
   "deb [arch=amd64] https://download.docker.com/linux/ubuntu \
   $(lsb_release -cs) \
   stable"

5.再更新一次包索引

$ sudo apt-get updata

6.安装docker engine

$ sudo apt-get install docker-ce docker-ce-cli containerd.io

等待就完成了~

分类
Algorithm C++

C++之父:链表是原罪吗?

翻译改编自https://isocpp.org/blog/2014/06/stroustrup-lists

链表是原罪吗?

作者:Bjarne Stroustrup

根据Web的某些角落,我的印象是向量总是比链表更好,而且我不了解其他数据结构,例如树(例如std::set)和哈希表(例如std::unordered_map)。显然,那是荒谬的。

问题似乎是约翰·本特利曾向我提出的一个有趣的小练习:将一系列随机整数插入到一个排序的序列中,然后按照原位置的顺序逐个删除这些元素定:你是否使用了vector(连续分配的元素序列)或list?我用这个例子来说明一些观点,鼓励思考算法,数据结构和机器架构,得出结论:

  • 不要不必要地存储数据
  • 保持数据紧凑
  • 以可预测的方式访问内存。

注意结论中没有vectorlist。请不要将示例与示例中的示例混淆。

这个例子的目的是说明一些一般原则并让人们思考。最初,大多数人说“当然选择list!”(我已经多次尝试过这个问题),因为“中间”有许多插入和删除(list很擅长)。这个答案是完全错误的。

我多年来一直在使用这个例子,并且让研究生实施并测量了这个练习和不同练习的几十种变体。其他人的例子和测量可以在网上找到。

  • 我尝试了map(它们比list要好得多,但仍比vector慢)
  • 我已经尝试了更大的元素大小
  • 我使用Binary Search和暴力插入向量(是的,它们甚至进一步加速)
  • 我查看了我的理论(不,我没有违反任何大O复杂性规则;只是某些操作对于一个数据结构而言比另一个更加昂贵)
  • 我有预先分配的链接(这比std::list遍历仍然性能更好)
  • 我使用了单链表forward_lists,(这没有多大区别,但是确保用户代码100%相当有点难度)
  • 我知道(并且说)500K列表并不常见(但这对我的要点无关紧要)。我们使用许多结构(大型和小型),其中可以选择链接和连续的表示。
  • 我知道listpush_front()更快,vectorpush_back()更快

我的观点不是关于列表。它们有它们的用途,但这个例子不是其中之一。请不要将示例与示例用于说明的内容混淆。这个例子是关于内存的使用:我们经常创建一个数据结构,对它进行一些需要访问的计算(通常是遍历),然后删除它。有序序列只是这种用法的一个例子,并且提供了示例以让人们思考在这种情况下重要的事情。我的建议是:

  • 不要不必要地存储数据
  • 保持数据紧凑
  • 以可预测的方式访问内存。

我强调cache的重要性。根据我的经验,除了真正的专家外,所有人都倾向于在讨论算法时忘记这些。

而且,是的,我的推荐是默认使用std::vector。更一般地说,除非有充分的理由不使用,否则请使用连续的表示。与C一样,C++默认设计用于执行此操作。

此外,请不要在没有测量的情况下对性能做出声明。我已经看到过这样一种情况,即将0-2元素列表更改为0-2元素向量会使算法产生因子2的差异。Nobody cares this.

分类
C++ OS

C/C++ 获取CPU核心数

有时候我们的多线程程序要确定并发数(线程数), 这时候我们可能比较关心当前环境CPU核心数

Windows

Windows为我们提供了一些API, 比如GetSystemInfo(), 可以获得当前系统的一些信息, 这个函数包含在<windows.h>中, 然后获取其中的dwNumberOfProcessors成员即可

#if defined(_WIN32)
SYSTEM_INFO info;
GetSystemInfo (&info);
return info.dwNumberOfProcessors;

Linux

Linux则更加方便, 直接调用GNU函数get_nprocs()即可

Code

所以代码如下:

int get_cpu_cores()
{
#if defined(_WIN32)
    SYSTEM_INFO info;
    GetSystemInfo (&info);
    return info.dwNumberOfProcessors;
#elif defined(LINUX) || defined(SOLARIS) || defined(AIX)
    return get_nprocs();   //GNU fuction
#else
#error  UNKNOWN OS!
#endif
}