用Python生成不同背景下显示内容不同的图片

今天在QQ群里看到这样一张图片,在手机上显示的时候,缩略图和点开之后看到的大图是完全不同的两个人。以前也在很多地方看到过点开之前和点开之后显示内容不同的图片,一直不知道其中的原理,于是想探究一番。

由于我不是很喜欢原图,这里用我喜欢的另一张图来说明。

首先把图片保存到电脑中,发现图片是png格式,而不是更常见的jpg。用Photoshop打开图片,效果如下:
amazing2

这些灰白相间的格子嘛,在Photoshop中表示透明。这说明图片中的大部分是透明的!那为什么在QQ中显示的不是这个样子呢?因为图片的后面有背景颜色!透明图片的特点就是在不同背景下显示的效果可以不一样。这也可以说明为什么图片是png格式,因为png格式可以有Alpha通道,而jpg没有。

在Photoshop中直接验证这个想法:

继续阅读“用Python生成不同背景下显示内容不同的图片”

绘制整系数多项式复数根的分布

我在百度贴吧Mathematica吧的这个帖子看到有人在研究如下问题:

求解所有系数为1或-1的n次多项式的根,然后把所有这样的根绘制到复平面上。

我想起以前在Matrix67的博客上也看到过这个问题,里面介绍了Sam Derbyshire用Mathematica跑了四天四夜(也有说法是三天三夜)生成了n=24的所有根,然后用Java程序绘图,得到了下图:

roots1

贴吧中的“三分钟复现”是算到n=17的情况。由于n增加1导致需要求解方程的数量翻倍,每个方程中根的个数也增加1,所以我估计了一下,n=24时大约需要求出24*2^24=402M个解。(24次多项式包括常数项有25个系数,但是由于对称性可以省去一半计算。)这些计算显然不需要以天为数量级的时间。

我决定用C语言解决这个问题,同时改善一下显示的效果,并尝试绘制分辨率更高的图。

解决这个问题有两个比较麻烦的事:

  • 如何求解多项式的根
  • 图上的颜色按照什么绘制

继续阅读“绘制整系数多项式复数根的分布”

C++的直接初始化与复制初始化

C++中的直接初始化指的是直接调用类的构造函数进行初始化,例如

string a; //调用默认构造函数
string a("hello"); //调用参数为const char *类型的构造函数
string b(a); //调用拷贝构造函数

复制初始化指的是用“=”号来初始化对象,例如

string a="hello";
string b=a;

在上面的例子中,这两种写法是完全等效的,但是直接初始化和复制初始化在一些情况下还是有区别的。

继续阅读“C++的直接初始化与复制初始化”

纯css让页脚固定在最下方

在制作网页时,我们通常喜欢在网页最下方放置一个页脚区域,在里面可以注明版权信息、备案信息、联系方式,也可以加一些链接、放置访问量统计等内容。

但是放置页脚时有一个非常棘手的问题:如果页脚直接跟在网页内容的下面,当网页内容不够一屏的时候,页脚不能保证在屏幕的底部,而是悬在屏幕中央,看起来很不美观。如果把页脚设置为固定在屏幕底部,如果网页内容超过一页,在我们浏览内容时页脚就会占用屏幕下方面积,甚至遮挡正文,在屏幕比较小的移动设备上面浏览时尤其明显。

我在这里介绍一种两全其美的方案,使得固定高度的页脚在内容较少时能够显示在屏幕的最下方,在内容较多时能够跟在网页下面。

继续阅读“纯css让页脚固定在最下方”

用Mathematica拟合自定义函数

最近在处理大物实验的数据时经常会遇到各种线性和非线性的拟合问题。对于线性回归的计算,用Excel电子表格,甚至卡西欧计算器,都很容易完成。但是对于复杂函数的拟合,简单的软件却无能为力。大物实验这门课推荐的Origin软件,拟合自定义函数很麻烦(据说需要编译成dll动态链接库),而且我不是很喜欢它的操作方式和界面。所以我选择用Mathematica来拟合自定义函数。

Mathematica的帮助文档是个好东西,不需要联网就可以根据你想要做的事情搜索相应的函数。

继续阅读“用Mathematica拟合自定义函数”

为什么C++直接输出21000可以精确到个位

这个想法源于一道程序设计课的上机题:任意给定一个正整数N(N<=100),计算2的n次方的值。 这道题的本意是练习高精度计算,但是可以发现,使用long double类型调用pow函数就足够了。当然我还是用高精度计算写的。 然而,我发现即使仅使用double,甚至用float,在C++中都可以输出正确的答案。 运行下面的C++代码:

#include<iostream>
#include<cmath>

using namespace std;

int main(){
    int x;
    cin>>x;
    cout.precision(0);
    cout<<fixed<<pow(2,x);
    return 0;
}

输入1000,程序输出一个超过300位的结果,虽然这早已超出double和long double的精度,但是运算结果是完全正确的。

至于结果的正确性,比较方便的方法就是与Python给出的结果进行对比。在Python的控制台中输入2**1000可以直接得到高精度计算的结果,很方便。

为什么结果是精确的呢?

继续阅读“为什么C++直接输出21000可以精确到个位”

C/C++中的const可信吗?

C和C++中有很多函数的参数类型使用了const这个关键字。例如C语言string.h头文件中的strcpy字符串复制函数,它的原型是

char * strcpy (char * Dest, const char * Source)

其中的const表示strcpy函数保证不修改Source指向的内存中的数据,而未加const的Dest指向的内容却可以被修改。

再如stdlib.h中的qsort快速排序函数原型如下:

void qsort (void * Base, size_t NumOfElements, size_t SizeOfElements, int (*PtFuncCompare)(const void *, const void *))

其中最后一个参数是一个函数指针,qsort需要你提供一个比较函数,这个比较函数以两个指针为参数,const要求你不能通过指针修改其指向的数据。

然而指针类型的参数加了const的函数就真的能保证它不会修改数据吗?

继续阅读“C/C++中的const可信吗?”

用freeshell提取自己百度云中一个压缩包里的文件

今天把一个很大的压缩包转存到了我的百度云网盘,但是压缩包里只有少数几个小文件是我所需要的。在寝室下载压缩包不但需要很长时间,而且会把网络带宽占满,影响自己和室友使用网络。于是我打算用freeshell(我们学校LUG社团提供的免费Linux主机)下载这个压缩包,在远程主机上解压文件,然后把需要的文件取回到自己的电脑。

Linux平台上没有百度云客户端。用别人提供的Linux百度云程序不仅需要现学,而且账号的安全性不能很好的保证。于是我决定用curl命令完全模拟自己电脑上网页版百度云的下载请求。

继续阅读“用freeshell提取自己百度云中一个压缩包里的文件”

用Mathematica计算物理题

昨天在做电磁学题目的时候遇到几个手算比较麻烦的式子,于是改用Mathematica软件完成了计算。

在这里总结两个解决方法:

1、做近似计算,略去高阶小量

有一道题要计算 \(r \gg l\) 时的电势分布,原始的式子是(去掉了常数部分)

$$\frac{1}{{\sqrt {{l^2} + 2lr\cos (\theta ) + {r^2}} }} + \frac{1}{{\sqrt {{l^2} – 2lr\cos (\theta ) + {r^2}} }} – \frac{2}{r}$$

在Mathematica中可以用Series函数计算这个函数在 \(l=0\) 处的泰勒展开,展开到第二项就可以了。

Mathematica输入如下:

Assuming[r>0,Simplify[Series[-2/r+1/Sqrt[r^2+l^2-2r l Cos[\[Theta]]]+1/Sqrt[r^2+l^2+2 r l Cos[\[Theta]]],{l,0,2}]]]

得到的结果是:

$$\frac{{\left( {1 + 3\cos \left[ {2 \theta} \right]} \right){l^2}}}{{2{r^3}}} + O{\left[ l \right]^3}$$

第一项就是所求。

2、在极坐标系中求梯度

根据刚才算出来的电势求电场强度矢量,需要在极坐标系中求梯度。

用Mathematica的Grad函数,输入如下:

Assuming[r>0,Simplify[-Grad[((1+3 Cos[2 \[Theta]]) l^2)/(2 r^3),{r,\[Theta],\[Phi]},"Spherical"]]]

得到的结果是:

$$\left\{ {\frac{{3{l^2}\left( {1 + 3\cos \left[ {2\theta } \right]} \right)}}{{2{r^4}}},\frac{{3{l^2}\sin \left[ {2\theta } \right]}}{{{r^4}}},0} \right\}$$

这里用的是球面坐标系,所以结果的第三个分量是0,可以略去。前两个分量分别代表\(r\)方向和\(\theta\)方向的结果。

【π Day】一段很短的计算圆周率的代码

今天是3月14日,圆周率日。

我在网上看到了一段很短的计算圆周率的代码,可以算到8000位。我把程序输出的结果和Mathematica的结果比较了一下,验证了程序是正确的。

通过更改c的值和f数组的大小,可以算到更多的位。

我没弄明白这段代码的原理,如果有谁知道,欢迎在回复中告诉我。

简短版:

#include<stdio.h>
int a=10000,b=0,c=28000,d,e=0,f[28010],g;
main(){
for(;b-c;)f[b++]=a/5;
for(;d=0,g=c*2;c-=14,printf("%04d",e+d/a),e=d%a)
for(b=c;d+=f[b]*a,f[b]=d%--g,d/=g--,--b;d*=b);
}

正常版:
继续阅读“【π Day】一段很短的计算圆周率的代码”