最近在处理一组数据的时候发现,linux和windows下处理的结果不同
经过层层排查,确定问题在os.listdir这个函数上
首先,我们知道相同代码,在不同的设备上结果是有可能不同的
原因参考 这里
1、代码写的不严谨比如C语言中:
int a=5;
int b=(a++)*(a++);
上边这段代码就可以出现不同的结果,原因是未定义行为:就是说C不能保证计算子表达式(a++)后增加1; 简单说C没有指明a是在每个子表达式被计算后增加还是整个表达式被计算后增加,应该避免使用这类语句。
2、编译器问题
C语言规范并没有对C语言的所有行为做定义,所以相同语句,不同编译器的运行效果可能有所不同。属比如同样的sizeof(int),在16位编译器上结果为2,而32位编译器上就会是4。
3、代码运行的平台硬件不同
不同的CPU,如嵌入式CPU,intel CPU,以及IBM的CPU,在硬件最底层就是不同的,而C语言是一门和底层相关性极大的语言,在不同的硬件上运行出不同结果是很正常的。
4、代码运行的系统不同。
相同CPU在不同操作系统上跑相同代码时,一样会出现不同的结果。这是由于系统底层的实现不同造成的。比如Linux和Windows,在底层处理上就有一定的差异。
5、代码获取到的外部数据不同。
比如运行代码时获取到的其它输入不同,包括程序中获取的环境变量,实时信息,以及各种外部输入等,均有可能出现不同。比如在做随机数时,如果以当前时间设定随机数种子,由于每次的时间是不同的,同一个程序每次运行的结果都是不同的。
而对于os.listdir这个函数而言,大概是原因4导致了结果不同
windows下的os.listdir是自动排序的
os.listdir(filepath)
对应的结果是
['a10t1.mat', 'a10t2.mat', 'a10t3.mat', 'a10t4.mat', 'a10t5.mat',
'a11t1.mat', 'a11t2.mat', 'a11t3.mat', 'a11t4.mat', 'a11t5.mat',
'a12t1.mat', 'a12t2.mat', 'a12t3.mat', 'a12t4.mat', 'a12t5.mat',
'a1t1.mat', 'a1t2.mat', 'a1t3.mat', 'a1t4.mat', 'a1t5.mat',
'a2t1.mat', 'a2t2.mat', 'a2t3.mat', 'a2t4.mat', 'a2t5.mat',
'a3t1.mat', 'a3t2.mat', 'a3t3.mat', 'a3t4.mat', 'a3t5.mat',
'a4t1.mat', 'a4t2.mat', 'a4t3.mat', 'a4t4.mat', 'a4t5.mat',
'a5t1.mat', 'a5t2.mat', 'a5t3.mat', 'a5t4.mat', 'a5t5.mat',
'a6t1.mat', 'a6t2.mat', 'a6t3.mat', 'a6t4.mat', 'a6t5.mat',
'a7t1.mat', 'a7t2.mat', 'a7t3.mat', 'a7t4.mat', 'a7t5.mat',
'a8t1.mat', 'a8t2.mat', 'a8t3.mat', 'a8t4.mat', 'a8t5.mat',
'a9t1.mat', 'a9t2.mat', 'a9t3.mat', 'a9t4.mat', 'a9t5.mat']
而linux下相同的代码,对应的结果却是
['a4t4.mat', 'a8t3.mat', 'a9t3.mat', 'a7t5.mat', 'a3t1.mat',
'a11t4.mat', 'a10t4.mat', 'a3t5.mat', 'a12t5.mat', 'a8t5.mat',
'a1t1.mat', 'a1t4.mat', 'a7t4.mat', 'a11t1.mat', 'a8t1.mat',
'a8t2.mat', 'a2t2.mat', 'a2t3.mat', 'a9t4.mat', 'a5t2.mat',
'a4t1.mat', 'a2t1.mat', 'a10t2.mat', 'a3t3.mat', 'a1t5.mat',
'a12t4.mat', 'a9t1.mat', 'a10t3.mat', 'a7t3.mat', 'a1t2.mat',
'a12t2.mat', 'a1t3.mat', 'a6t5.mat', 'a4t5.mat', 'a5t1.mat',
'a10t5.mat', 'a9t2.mat', 'a11t2.mat', 'a2t5.mat', 'a7t2.mat',
'a6t4.mat', 'a6t2.mat', 'a6t1.mat', 'a2t4.mat', 'a8t4.mat',
'a3t2.mat', 'a11t3.mat', 'a12t1.mat', 'a9t5.mat', 'a3t4.mat',
'a4t2.mat', 'a11t5.mat', 'a7t1.mat', 'a4t3.mat', 'a5t3.mat',
'a5t4.mat', 'a5t5.mat', 'a10t1.mat', 'a12t3.mat', 'a6t3.mat']
可见,是没有自动排序的
如果我们将linux下的代码改为
sorted(os.listdir(filepath))
对应的结果如下,和windows下的结果相同
['a10t1.mat', 'a10t2.mat', 'a10t3.mat', 'a10t4.mat', 'a10t5.mat',
'a11t1.mat', 'a11t2.mat', 'a11t3.mat', 'a11t4.mat', 'a11t5.mat',
'a12t1.mat', 'a12t2.mat', 'a12t3.mat', 'a12t4.mat', 'a12t5.mat',
'a1t1.mat', 'a1t2.mat', 'a1t3.mat', 'a1t4.mat', 'a1t5.mat',
'a2t1.mat', 'a2t2.mat', 'a2t3.mat', 'a2t4.mat', 'a2t5.mat',
'a3t1.mat', 'a3t2.mat', 'a3t3.mat', 'a3t4.mat', 'a3t5.mat',
'a4t1.mat', 'a4t2.mat', 'a4t3.mat', 'a4t4.mat', 'a4t5.mat',
'a5t1.mat', 'a5t2.mat', 'a5t3.mat', 'a5t4.mat', 'a5t5.mat',
'a6t1.mat', 'a6t2.mat', 'a6t3.mat', 'a6t4.mat', 'a6t5.mat',
'a7t1.mat', 'a7t2.mat', 'a7t3.mat', 'a7t4.mat', 'a7t5.mat',
'a8t1.mat', 'a8t2.mat', 'a8t3.mat', 'a8t4.mat', 'a8t5.mat',
'a9t1.mat', 'a9t2.mat', 'a9t3.mat', 'a9t4.mat', 'a9t5.mat']
换句话说,实际上,windows下的os.listdir(filepath)等价于linux下的sorted(os.listdir(filepath))
也正是这个问题,导致了后续计算mean和std时候的不同,一切玄学的本质都是未搞明白的科学,这也是为啥完全一样的代码,后续精度会差距很大