仓库源文站点原文


layout: post title: 取整截断函数及其在PBC中的使用 categories:


2013-08-13 14:05:39

取整和截断相关的函数, 有着各种不同的名称, 不同的定义, 很容易让人迷惑. 它们之间根据具体情况还可以相互转换成不同的写法, 更增添了混乱. 下面整理Fortran和C中的相关函数.

<table><caption>取整截断函数</caption> <tr> <th style="text-align:center;"> 函数 </th> <th style="text-align:center;"> Fortran </th> <th colspan="2" style="text-align:center;"> C </th> </tr> <tr> <td style="text-align:center;"> 向下取整⌊x⌋ </td> <td style="text-align:center;"> floor </td> <td colspan="2" style="text-align:center;"> floor</td> </tr> <tr> <td style="text-align:center;"> 向上取整⌈x⌉ </td> <td style="text-align:center;"> ceiling </td> <td colspan="2" style="text-align:center;"> ceil</td> </tr> <tr> <td style="text-align:center;"> 截断取整[x] </td> <td style="text-align:center;"> int/aint </td> <td colspan="2" style="text-align:center;"> int</td> </tr> <tr> <td style="text-align:center;"> 四舍五入 </td> <td style="text-align:center;"> nint/anint </td> <td colspan="2" style="text-align:center;"> round</td> </tr> <tr> <td rowspan="2" style="text-align:center;"> 模/取余 </td> <td style="text-align:center;"> mod(x,p)=x-int(x/p)*p </td> <td rowspan="2" colspan="2" style="text-align:center;"> x%p</td> </tr> <tr> <td style="text-align:center;"> modulo(x,p)=x-floor(x/p)*p </td> </tr> <tr> <td style="text-align:center;"> 绝对值 |x| </td> <td style="text-align:center;"> abs </td> <td colspan="2" style="text-align:center;"> abs</td> </tr> <tr> <td style="text-align:center;"> 符号 </td> <td style="text-align:center;"> sign(x, y) </td> <td colspan="2" style="text-align:center;"> </td> </tr> </table>

此外, 数学上还会使用如下去整函数

$frac(x)={x}=x-\lfloor x \rfloor=mod(x,1)$

以上这些函数组合起来, 基本能满足各种需要了.

下面是各个函数的图像, 数值可参看附表

由图像与数值可知

$$int(x) = [x] = \begin{cases} \lfloor x \rfloor, & x>0 \ \lceil x \rceil, & x<0 \end{cases}$$

$$nint(x) = \begin{cases} int(x+1/2) = \lfloor x+1/2 \rfloor, & x>0 \ int(x-1/2) = \lceil x-1/2 \rceil, & x<0 \end{cases}$$

周期性边界条件PBC在使用时有两种情况, 设盒子长度为L, 粒子坐标为x

  1. 以左下角为坐标原点, 坐标 $x \in [0,L)$, 为使粒子处于盒内, 须 $x=x-\lfloor x \rfloor$
  2. 以中心为原点, 坐标 $x \in [-L/2,L/2)$, 常用于计算粒子之间距离, 此时又分两种情况

另外, 若想实现一定时间间隔 $\Delta t$ 取样, 本可利用 $mod(t, \Delta t)=t-\lfloor t/\Delta t \rfloor$ 实现. 但由于取整问题(前面说过), 遇到特定时间间隔时就会失效, 变通的方法是判断 $t$ 恰好能被 $\Delta t$ 整除, 即t的小数部分 ${t}$ 为零. 用 $t-nint(t/\Delta t)\Delta t$ 或 $mod(t+\Delta t/2, \Delta t)-\Delta t/2$ 可避免此问题.

参考

  1. http://en.wikipedia.org/wiki/Floor_and_ceiling_functions
  2. http://en.wikipedia.org/wiki/Periodic_boundary_conditions
<table><caption>取整截断函数取值表</caption> <tr> <th style="text-align:center;"> x </th> <th style="text-align:center;">floor</th> <th style="text-align:center;">ceiling</th> <th style="text-align:center;">int</th> <th style="text-align:center;">nint</th> <th style="text-align:center;">int(x+0.5)</th> <th style="text-align:center;">int(x-0.5)</th> </tr> <tr> <td style="text-align:center;"> -2.00 </td> <td rowspan="4" style="text-align:center;"> -2 </td> <td style="text-align:center;"> -2 </td> <td style="text-align:center;"> -2 </td> <td rowspan="3" style="text-align:center;"> -2 </td> <td rowspan="3" style="text-align:center;"> -1 </td> <td rowspan="3" style="text-align:center;"> -2 </td> </tr> <tr> <td style="text-align:center;"> -1.80 </td> <td rowspan="4" style="text-align:center;"> -1 </td> <td rowspan="4" style="text-align:center;"> -1 </td> </tr> <tr> <td style="text-align:center;"> -1.50 </td> </tr> <tr> <td style="text-align:center;"> -1.20 </td> <td rowspan="7" style="text-align:center;"> -1 </td> <td rowspan="16" style="text-align:center;"> 0 </td> <td rowspan="7" style="text-align:center;"> -1 </td> </tr> <tr> <td style="text-align:center;"> -1.00 </td> <td rowspan="10" style="text-align:center;"> -1 </td> </tr> <tr> <td style="text-align:center;"> -0.90 </td> <td rowspan="10" style="text-align:center;"> 0 </td> <td rowspan="19" style="text-align:center;"> 0 </td> </tr> <tr> <td style="text-align:center;"> -0.80 </td> </tr> <tr> <td style="text-align:center;"> -0.70 </td> </tr> <tr> <td style="text-align:center;"> -0.60 </td> </tr> <tr> <td style="text-align:center;"> -0.50 </td> </tr> <tr> <td style="text-align:center;"> -0.40 </td> <td rowspan="9" style="text-align:center;"> 0 </td> <td rowspan="17" style="text-align:center;"> 0 </td> </tr> <tr> <td style="text-align:center;"> -0.30 </td> </tr> <tr> <td style="text-align:center;"> -0.20 </td> </tr> <tr> <td style="text-align:center;"> -0.10 </td> </tr> <tr> <td style="text-align:center;"> 0.00 </td> <td rowspan="10" style="text-align:center;"> 0 </td> </tr> <tr> <td style="text-align:center;"> 0.10 </td> <td rowspan="10" style="text-align:center;"> 1 </td> </tr> <tr> <td style="text-align:center;"> 0.20 </td> </tr> <tr> <td style="text-align:center;"> 0.30 </td> </tr> <tr> <td style="text-align:center;"> 0.40 </td> </tr> <tr> <td style="text-align:center;"> 0.50 </td> <td rowspan="8" style="text-align:center;"> 1 </td> <td rowspan="8" style="text-align:center;"> 1 </td> </tr> <tr> <td style="text-align:center;"> 0.60 </td> </tr> <tr> <td style="text-align:center;"> 0.70 </td> </tr> <tr> <td style="text-align:center;"> 0.80 </td> </tr> <tr> <td style="text-align:center;"> 0.90 </td> </tr> <tr> <td style="text-align:center;"> 1.00 </td> <td rowspan="5" style="text-align:center;"> 1 </td> <td rowspan="5" style="text-align:center;"> 1 </td> </tr> <tr> <td style="text-align:center;"> 1.10 </td> <td rowspan="5" style="text-align:center;"> 2 </td> </tr> <tr> <td style="text-align:center;"> 1.20 </td> </tr> <tr> <td style="text-align:center;"> 1.50 </td> <td rowspan="3" style="text-align:center;"> 2 </td> <td rowspan="3" style="text-align:center;"> 2 </td> <td rowspan="3" style="text-align:center;"> 1 </td> </tr> <tr> <td style="text-align:center;"> 1.80 </td> </tr> <tr> <td style="text-align:center;"> 2.00 </td> <td style="text-align:center;"> 2 </td> <td style="text-align:center;"> 2 </td> </tr> </table>