模拟生成一天温度数据,精确到秒
需求来源:
做一套养殖过程管理的系统,有养殖环境数据采集功能,硬件不到位,需要给相关LD演示,要求数据尽量真实。这就需要模拟生成一天的温度数据。
解决方案1:
指定范围随机数温度生成
结果就是这样了。。。太假。。。
解决方案2:
代码连续随机数生成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 | $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一下,绘图,和原图一致,但得到了精确到秒的一天的温度数据。
问题:得到的温度曲线还是有点太“光滑了”,使用随机数波动一下效果也不靠谱。
哪位有更好的模拟方法、精确的模拟算法、更真实的模拟结果 或者 直接有精确到秒的温度数据 更或者,直接有我这个问题的解决方案,可以给在下指点一二。
码字不易,转载请注明出处,谢谢! 2017-04-22
续:
使用中又发现一利器,数据点随意拖动啊!!!太实用了!!!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库