做一套养殖过程管理的系统,有养殖环境数据采集功能,硬件不到位,需要给相关 LD 演示,要求数据尽量真实。这就需要模拟生成一天的温度数据。
解决方案 1:
指定范围随机数温度生成
结果就是这样了。。。太假。。。
解决方案 2:
代码连续随机数生成:
- $wd_arr = array(); // 温度
- //-------------温度--------------
- // 生成连续的温度随机数
- $wd_start = 21.6;
- $MAX_WD = 22.6; //最高温度22.6
- $MIN_WD = 7.1; // 最低温度7.1
- $START_OFFSET_WD = 5*60*2; // 从5点开始
- $WD_diff = $MAX_WD - $MIN_WD; // 温度差
- $WD_change_prob = 0.1; // 温度变化概率
- // 模拟一天的气温,2880为每半分钟采集一次
- $wd_arr[$START_OFFSET_WD] = $MIN_WD;
- $wd_inte1 = getRandFW( (14-5)*60*2, $WD_diff ); // 第一段的区间
- $wd_inte2 = getRandFW( (21-14)*60*2, $WD_diff * 0.9 ); // 第二段的区间
- $wd_inte3 = getRandFW( (24-21 + 5)*60*2, $WD_diff * 0.1 ); // 第三段的区间
- // 模拟生成数据
- for($i=1; $i<=24*60*2; $i++){
- // ----------- 温度 -------------
- // 5~14点,90%概率温度不变, 10%概率温度增加
- if($START_OFFSET_WD + $i < 14*60*2 && $START_OFFSET_WD + $i > 5*60*2) {
- $is_change = false;
- $rd = mt_rand(1,100);
- if($rd<=100 * $WD_change_prob) {
- $is_change = true;
- }
- // 升温
- $rd = 0;
- if($is_change) {
- //每次增加的温度是[0.007 ~ 0.28]*100 四舍五入 再 除以100后的随机数
- //$rd = mt_rand(7,280);
- //$rd = round ($rd / 10)/100; // 除以10然后四舍五入
- //$inte = getRandFW( (14-5)*60*2, $WD_diff );
- $rd = mt_rand($wd_inte1['start'], $wd_inte1['end']);
- $rd = round(round ($rd / 10)/100,2);
- }
- $wd_arr[$START_OFFSET_WD + $i] = $wd_arr[$START_OFFSET_WD + $i - 1] + $rd;
- } else if ( ($START_OFFSET_WD + $i > 14*60*2) && ($START_OFFSET_WD + $i < 21*60*2) ) { // 14点以后21点之前,降低温度差的90%
- $is_change = false;
- $rd = mt_rand(1,100);
- if($rd<=100 * $WD_change_prob) {
- $is_change = true;
- }
- // 降温
- $rd = 0;
- if($is_change) {
- //$inte = getRandFW( (21-14)*60*2, $WD_diff * 0.9 );
- $rd = mt_rand($wd_inte2['start'], $wd_inte2['end']);
- $rd = round(round ($rd / 10)/100,2);
- }
- $wd_arr[$START_OFFSET_WD + $i] = $wd_arr[$START_OFFSET_WD + $i - 1] - $rd;
- } else { // 21点之后,5点之前,降低温度差的10%
- $is_change = false;
- $rd = mt_rand(1,100);
- if($rd<=100 * $WD_change_prob) {
- $is_change = true;
- }
- $index = $START_OFFSET_WD + $i;
- $index > 24*60*2 ? $index-=(24*60*2+1) : $index=$index;
- // 降温
- $rd = 0;
- if($is_change) {
- //$inte = getRandFW( (24-21 + 5)*60*2, $WD_diff * 0.1 );
- $rd = mt_rand($wd_inte3['start'], $wd_inte3['end']);
- $rd = round(round ($rd / 10)/100,2);
- }
- // 大于2880
- $index = $START_OFFSET_WD + $i;
- $index > 24*60*2 ? $index-=(24*60*2+1) : $index=$index;
- //echo $index." --- ";
- $index != 0 ? $wd_arr[$index] = $wd_arr[$index-1] - $rd : $wd_arr[$index] = $wd_arr[24*60*2] - $rd;
- //echo $wd_arr[$index]."<br />";
- //$wd_arr[$index] = $wd_arr[$index-1] + $rd;
- }
- date_default_timezone_set('PRC');
- for($i=0; $i<24*60*2; $i++ ) {
- $nowDatestep = strtotime(date("Y-m-d",time()));
- $nowtimestep = ( (intval($i/(2*60)))*3600 + (($i-($i%2==0?0:1))/2 - (intval($i/(2*60)))*60)*60 + ($i%2==0 ? 0:30) );
- $newdatetimestep = $nowDatestep + $nowtimestep;
- $nowformatTime = (intval($i/(2*60))).':'.(($i-($i%2==0?0:1))/2 - (intval($i/(2*60)))*60).':'.($i%2==0?'00':'30');
- // echo $newdatetimestep .' '. $nowformatTime. ' ' . $wd_arr[$i]. ' ' . $sd_arr[$i]. ' ' . $gz_arr[$i]. ' ' . $aq_arr[$i]. ' ' . $yhqt_arr[$i].'<br>';
- echo $newdatetimestep .' '. $nowformatTime. ' ' . $wd_arr[$i]. '<br>';
- //echo " ".( (intval($i/(2*60)))*3600 + (($i-($i%2==0?0:1))/2 - (intval($i/(2*60)))*60)*60 + ($i%2==0 ? 0:30) )." ".(intval($i/(2*60))).':'.(($i-($i%2==0?0:1))/2 - (intval($i/(2*60)))*60).':'.($i%2==0?'00':'30')." ".$wd_arr[$i].'<br>';
- //echo $i.'---'.$wd_arr[$i].'<br>';
- }
- /*
- * 根据温度差和时间范围确定变化率和范围
- * @ 时间差
- * @ 温度差
- *
- */
- function getRandFW($Time_diff, $WD_diff){
- // 10%的时间里温度在降
- $bl = round( ($WD_diff / ( $Time_diff * 0.1 ) ) * 2 * 1000 );
- // 获得个位数然后
- $inte['start'] = ($bl % 10);
- // 获得除了个位后的数
- $inte['end'] = $bl - ($bl % 10);
- return $inte;
- }
效果也不尽如人意。。。
解决方案 3:
使用真实离散温度 -》 生成平滑曲线 -》 生成秒级数据
第一步:去中国天气网找当地附近一天的真实温度数据,可惜只有 24 小时,温度值还是整数。。。还是整数。。。还是整数。。。
第二步:输入到 excel 中,适当的手工和修改一下小数点后的数据,模拟画个图,基本真实吧。
第三步:在 excel 中,将 0、1、2、替换成一天的秒数,为了连续,将首位从 1 开始
第四步,安装此函数绘图神器,Origin Pro,将 excel 中的数据粘至次神器中,选中 A B 列并画直线。
第五步:根据曲线,生成,每秒的数据。(拿箭头工具选中曲线,然后操作一下菜单)
要生成 86400 个点,如图:
此时又出现两列新的数据,这两列数据就是我们要的每秒的温度值。
将新生成的这两列数,粘如 excel 中,round 一下,绘图,和原图一致,但得到了精确到秒的一天的温度数据。
问题:得到的温度曲线还是有点太 "光滑了",使用随机数波动一下效果也不靠谱。
哪位有更好的模拟方法、精确的模拟算法、更真实的模拟结果 或者 直接有精确到秒的温度数据 更或者,直接有我这个问题的解决方案,可以给在下指点一二。
来源: http://www.cnblogs.com/dwj192/p/6747503.html