模拟生成一天温度数据,精确到秒

Posted 河在谈

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了模拟生成一天温度数据,精确到秒相关的知识,希望对你有一定的参考价值。

需求来源:

  做一套养殖过程管理的系统,有养殖环境数据采集功能,硬件不到位,需要给相关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一下,绘图,和原图一致,但得到了精确到秒的一天的温度数据。

    

 

 

 

     问题:得到的温度曲线还是有点太“光滑了”,使用随机数波动一下效果也不靠谱。

    

     哪位有更好的模拟方法、精确的模拟算法、更真实的模拟结果 或者 直接有精确到秒的温度数据 更或者,直接有我这个问题的解决方案,可以给在下指点一二。

    码字不易,转载请注明出处,谢谢!    2017-04-22

 

    续:

    使用中又发现一利器,数据点随意拖动啊!!!太实用了!!!

    

 

以上是关于模拟生成一天温度数据,精确到秒的主要内容,如果未能解决你的问题,请参考以下文章

第二阶段冲刺6

c++计算时间差(精确到秒)

Win10时钟精确到秒

mybatis 插入日期类型精确到秒的有关问题

C语言计算两个时间之间的时间差,精确到秒。 现在我用的是time_t来计算的,但是我发现这个tim

String 转换成精确到秒的 sql.Date类型问题