工业数学模型——高炉煤气发生量预测(三)

1、工业场景

冶金过程中生产的各种煤气,例如高炉煤气、焦炉煤气、转炉煤气等。作为重要的副产品和二次能源,保证它们的梯级利用和减少放散是煤气能源平衡调控的一项紧迫任务,准确的预测煤气的发生量是实现煤气系统在线最优调控的前提。

2、数学模型

本次研究主要采用了长短记忆模型(LSTM)预测了正常工况下的高炉煤气发生量。后续研究方向希望将正常工况扩展到变化工况条件下,例如休风、减产、停产、检修等条件下煤气发生量,并引入更多特征维度,例如:焦比、煤比、风量、富氧、风温、风压、炉内压差等。下面重点介绍一下LSTM网络结构。

长短期记忆网络(LSTM,Long Short-Term Memory)是一种时间循环神经网络,是为了解决一般的RNN(循环神经网络)存在的长期依赖问题而专门设计出来的,所有的RNN都具有一种重复神经网络模块的链式形式。
在这里插入图片描述这张图片是经典的LSTM网络结构的图片,但是不好理解,图片把多维的空间结构压缩成了二维图片,所以需要大家脑补一下,回放到立体空间中去理解。相对比RNN 通过时间步骤地更新隐藏状态和输出结果。而LSTM 通过输入门、遗忘门和输出门来控制隐藏状态的更新和输出。在这里不过多的去讲解模型结构,大家可以从网上了解一下,LSTM网络模型作为世纪霸主被广泛应用于自然语言处理、语音识别、图像处理等领域。总之很厉害!

3、数据准备

本次数据收集了1#高炉从4月12日0点到4月16日0点72小时的煤气累计发生量数据,时间间隔为60000ms也就是1分钟一次点位数据,通过计算获取5760个分钟级的煤气发生量数据。
如图:第一个字段是数采时序库中的点位标识,第二个字段是时间,第三个字段是当前煤气发生量累计值,第四个字段是计算获得的当前分钟内煤气发生量。

在这里插入图片描述

4、模型构建

class LSTM(nn.Module):
    """
    LSMT网络搭建
    """

    def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size):
        super().__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.output_size = output_size
        self.num_directions = 1  # 单向LSTM
        self.batch_size = batch_size
        self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, batch_first=True)
        self.linear = nn.Linear(self.hidden_size, self.output_size)

    def forward(self, input_seq):
        batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]
        h_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size)
        c_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size)
        output, _ = self.lstm(input_seq, (h_0, c_0))
        pred = self.linear(output)
        pred = pred[:, -1, :]
        return pred


5、模型训练

①数据预处理:加载数据文件,原始数据文件为csv(通过1#高炉84小时内煤气发生量累计值,时间间隔为60000ms,计算出84小时内每分钟的发生量)将数据分为训练集:验证集:测试集=3:1:1。

def load_data(file_name):
    """
    加载数据文件,原始数据文件为csv(通过1#高炉24小时内煤气发生量累计值,时间间隔为60000ms,计算出24小时内每分钟的发生量)
    :param file_name csv文件的绝对路径
    :return 训练集、验证集、测试集、训练集中最大值、训练集中最小值
    训练集:验证集:测试集=3:1:1
    """
    dataset = pd.read_csv('D:\\LIHAOWORK\\' + file_name, encoding='gbk')
    train = dataset[:int(len(dataset) * 0.6)]
    val = dataset[int(len(dataset) * 0.6):int(len(dataset) * 0.8)]
    test = dataset[int(len(dataset) * 0.8):len(dataset)]
    max, nin = np.max(train[train.columns[3]]), np.min(train[train.columns[3]])  # 分钟内发生量是csv中第四个字段
    return train, val, test, max, nin

②数据组装:把数据组装成训练、验证、测试需要的格式。实质是90个顺序数据为一组作为输入值x,第91个作为真实发生值y,如此循环。

def process_data(data, batch_size, shuffle, m, n, k):
    """
    数据处理
    :param data 待处理数据
    :param batch_size 批量大小
    :param shuffle 是否打乱
    :param m 最大值
    :param n 最小值
    :param k 序列长度
    :return 处理好的数据
    """
    data_3 = data.iloc[0:, [3]].to_numpy().reshape(-1)  #
    data_3 = data_3.tolist()
    data = data.values.tolist()
    data_3 = (data_3 - n) / (m - n)
    feature = []
    label = []
    for i in range(len(data) - k):
        train_seq = []
        train_label = []
        for j in range(i, i + k):
            x = [data_3[j]]
            train_seq.append(x)
        train_label.append(data_3[i + k])
        feature.append(train_seq)
        label.append(train_label)
    feature_tensor = torch.FloatTensor(feature)
    label_tensor = torch.FloatTensor(label)
    data = TensorDataset(feature_tensor, label_tensor)
    data_loader = DataLoader(dataset=data, batch_size=batch_size, shuffle=shuffle, num_workers=0, drop_last=True)
    return data_loader

③模型训练:输入大小为1;隐藏层大小为128,隐藏层数为1,输出大小为1,批量大小为5,学习率为0.01,训练次数3。

def train(Dtr, Val, path):
    """
    训练
    :param Dtr 训练集
    :param Val 验证集
    :param path 模型保持路劲
    """
    input_size = 1
    hidden_size = 128
    num_layers = 1
    output_size = 1
    epochs = 5
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=5)
    loss_function = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=1e-4)
    # optimizer = torch.optim.SGD(model.parameters(), lr=0.05, momentum=0.9, weight_decay=1e-4)
    scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
    # start training
    for epoch in tqdm(range(epochs)):
        train_loss = []
        for (seq, label) in Dtr:
            y_pred = model(seq)
            loss = loss_function(y_pred, label)
            train_loss.append(loss.item())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        scheduler.step()
        # validation
        model.eval()
        val_loss = []
        for seq, label in Val:
            y_pred = model(seq)
            loss = loss_function(y_pred, label)
            val_loss.append(loss.item())
        print('epoch {:03d} train_loss {:.8f} val_loss {:.8f}'.format(epoch, np.mean(train_loss), np.mean(val_loss)))
        model.train()
    state = {'models': model.state_dict()}
    torch.save(state, path)

训练过程如下:
在这里插入图片描述

④模型测试:

def test(Dte, path, m, n):
    """
    测试
    :param Dte 测试集
    :param path 模型
    :param m 最大值
    :param n 最小值
    """
    pred = []
    y = []
    input_size = 1
    hidden_size = 128
    num_layers = 1
    output_size = 1
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=5)
    model.load_state_dict(torch.load(path)['models'])
    model.eval()
    for (seq, target) in tqdm(Dte):
        y.extend(target)
        with torch.no_grad():
            y_pred = model(seq)
            pred.extend(y_pred)

    y, pred = np.array(y), np.array(pred)
    y = (m - n) * y + n
    pred = (m - n) * pred + n

    # 出图
    x = [i for i in range(len(y))]
    x_smooth = np.linspace(np.min(x), np.max(x), 1000)
    y_smooth = make_interp_spline(x, y)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=1, label='true')

    y_smooth = make_interp_spline(x, pred)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=1, label='pred')
    plt.grid(axis='y')
    plt.legend()
    plt.show()

直接对比图:红色线为模型在测试数据集上的预测值,绿色线为真实的发生值。
在这里插入图片描述有点密密麻麻,我们可以看一下局部
在这里插入图片描述在这里插入图片描述⑤滚动测试30分钟内发生值,利用前90分钟的真实发生值预测第91分钟的发生值,再将第91分钟的发生值加入到输入中,预测第92分钟的发生值,以此类推,预测30分钟内的高炉煤气发生量。

def test_rolling(Dte, path, m, n):
    """
    滚动测试,预测30条
    :param Dte 测试集
    :param path 模型
    :param m 最大值
    :param n 最小值
    """
    pred = []
    y = []
    input_size = 1
    hidden_size = 128
    num_layers = 1
    output_size = 1
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=1)
    model.load_state_dict(torch.load(path)['models'])
    model.eval()
    i = 0  # 控制滚动预测的长度,这里计划通过前90分钟内的发生量预测后30分钟内的发生量
    for (seq, target) in tqdm(Dte):
        y.extend(target)
        with torch.no_grad():
            seq = seq.numpy().tolist()[0]
            seq.extend(pred)  # 预测值追加到后面
            seq = seq[-90:]   # 截取后90条数据,滚动预测
            seq = torch.tensor(seq).resize(1, 90, 1)
            y_pred = model(seq)
            pred.extend(y_pred)
        i = i + 1
        if i >= 30:  # 控制滚动预测的长度,这里计划通过前90分钟内的发生量预测后30分钟内的发生量
            break

    y, pred = np.array(y), np.array(pred)
    y = (m - n) * y + n
    pred = (m - n) * pred + n

    # 出图
    x = [i for i in range(len(y))]
    x_smooth = np.linspace(np.min(x), np.max(x), 1000)
    y_smooth = make_interp_spline(x, y)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=1, label='true')

    y_smooth = make_interp_spline(x, pred)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=1, label='pred')
    plt.grid(axis='y')
    plt.legend()
    plt.show()

出图
在这里插入图片描述有点过分拟合
调整参数num_layers = 2 增加dropout=0.3 后
在这里插入图片描述整体效果不是很理想,可能再调一下参会好一些。
目前的完整代码如下:

import pandas as pd
import numpy as np
import torch
from matplotlib import pyplot as plt
from scipy.interpolate import make_interp_spline
from torch import nn
from torch.optim.lr_scheduler import StepLR
from torch.utils.data import DataLoader, TensorDataset
from tqdm import tqdm


def load_data(file_name):
    """
    加载数据文件,原始数据文件为csv(通过1#高炉24小时内煤气发生量累计值,时间间隔为60000ms,计算出24小时内每分钟的发生量)
    :param file_name csv文件的绝对路径
    :return 训练集、验证集、测试集、训练集中最大值、训练集中最小值
    训练集:验证集:测试集=3:1:1
    """
    dataset = pd.read_csv('D:\\LIHAOWORK\\' + file_name, encoding='gbk')
    train = dataset[:int(len(dataset) * 0.6)]
    val = dataset[int(len(dataset) * 0.6):int(len(dataset) * 0.8)]
    test = dataset[int(len(dataset) * 0.8):len(dataset)]
    max, nin = np.max(train[train.columns[3]]), np.min(train[train.columns[3]])  # 分钟内发生量是csv中第四个字段
    return train, val, test, max, nin


def process_data(data, batch_size, shuffle, m, n, k):
    """
    数据处理
    :param data 待处理数据
    :param batch_size 批量大小
    :param shuffle 是否打乱
    :param m 最大值
    :param n 最小值
    :param k 序列长度
    :return 处理好的数据
    """
    data_3 = data.iloc[0:, [3]].to_numpy().reshape(-1)  #
    data_3 = data_3.tolist()
    data = data.values.tolist()
    data_3 = (data_3 - n) / (m - n)
    feature = []
    label = []
    for i in range(len(data) - k):
        train_seq = []
        train_label = []
        for j in range(i, i + k):
            x = [data_3[j]]
            train_seq.append(x)
        train_label.append(data_3[i + k])
        feature.append(train_seq)
        label.append(train_label)
    feature_tensor = torch.FloatTensor(feature)
    label_tensor = torch.FloatTensor(label)
    data = TensorDataset(feature_tensor, label_tensor)
    data_loader = DataLoader(dataset=data, batch_size=batch_size, shuffle=shuffle, num_workers=0, drop_last=True)
    return data_loader


class LSTM(nn.Module):
    """
    LSMT网络搭建
    """

    def __init__(self, input_size, hidden_size, num_layers, output_size, batch_size):
        super().__init__()
        self.input_size = input_size
        self.hidden_size = hidden_size
        self.num_layers = num_layers
        self.output_size = output_size
        self.num_directions = 1  # 单向LSTM
        self.batch_size = batch_size
        self.lstm = nn.LSTM(self.input_size, self.hidden_size, self.num_layers, dropout=0.3, batch_first=True)
        self.linear = nn.Linear(self.hidden_size, self.output_size)

    def forward(self, input_seq):
        batch_size, seq_len = input_seq.shape[0], input_seq.shape[1]
        h_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size)
        c_0 = torch.randn(self.num_directions * self.num_layers, self.batch_size, self.hidden_size)
        output, _ = self.lstm(input_seq, (h_0, c_0))
        pred = self.linear(output)
        pred = pred[:, -1, :]
        return pred


def train(Dtr, Val, path):
    """
    训练
    :param Dtr 训练集
    :param Val 验证集
    :param path 模型保持路劲
    """
    input_size = 1
    hidden_size = 128
    num_layers = 2
    output_size = 1
    epochs = 3
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=5)
    loss_function = nn.MSELoss()
    optimizer = torch.optim.Adam(model.parameters(), lr=0.01, weight_decay=1e-4)
    # optimizer = torch.optim.SGD(model.parameters(), lr=0.05, momentum=0.9, weight_decay=1e-4)
    scheduler = StepLR(optimizer, step_size=30, gamma=0.1)
    # start training
    for epoch in tqdm(range(epochs)):
        train_loss = []
        for (seq, label) in Dtr:
            y_pred = model(seq)
            loss = loss_function(y_pred, label)
            train_loss.append(loss.item())
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()
        scheduler.step()
        # validation
        model.eval()
        val_loss = []
        for seq, label in Val:
            y_pred = model(seq)
            loss = loss_function(y_pred, label)
            val_loss.append(loss.item())
        print('epoch {:03d} train_loss {:.8f} val_loss {:.8f}'.format(epoch, np.mean(train_loss), np.mean(val_loss)))
        model.train()
    state = {'models': model.state_dict()}
    torch.save(state, path)


def test(Dte, path, m, n):
    """
    测试
    :param Dte 测试集
    :param path 模型
    :param m 最大值
    :param n 最小值
    """
    pred = []
    y = []
    input_size = 1
    hidden_size = 128
    num_layers = 2
    output_size = 1
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=5)
    model.load_state_dict(torch.load(path)['models'])
    model.eval()
    for (seq, target) in tqdm(Dte):
        y.extend(target)
        with torch.no_grad():
            y_pred = model(seq)
            pred.extend(y_pred)

    y, pred = np.array(y), np.array(pred)
    y = (m - n) * y + n
    pred = (m - n) * pred + n

    # 出图
    x = [i for i in range(len(y))]
    x_smooth = np.linspace(np.min(x), np.max(x), 1000)
    y_smooth = make_interp_spline(x, y)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=1, label='true')

    y_smooth = make_interp_spline(x, pred)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=1, label='pred')
    plt.grid(axis='y')
    plt.legend()
    plt.show()


def test_rolling(Dte, path, m, n):
    """
    滚动测试,预测30条
    :param Dte 测试集
    :param path 模型
    :param m 最大值
    :param n 最小值
    """
    pred = []
    y = []
    input_size = 1
    hidden_size = 128
    num_layers = 2
    output_size = 1
    model = LSTM(input_size, hidden_size, num_layers, output_size, batch_size=1)
    model.load_state_dict(torch.load(path)['models'])
    model.eval()
    i = 0  # 控制滚动预测的长度,这里计划通过前90分钟内的发生量预测后30分钟内的发生量
    for (seq, target) in tqdm(Dte):
        y.extend(target)
        with torch.no_grad():
            seq = seq.numpy().tolist()[0]
            seq.extend(pred)  # 预测值追加到后面
            seq = seq[-90:]   # 截取后90条数据,滚动预测
            seq = torch.tensor(seq).resize(1, 90, 1)
            y_pred = model(seq)
            pred.extend(y_pred)
        i = i + 1
        if i >= 30:  # 控制滚动预测的长度,这里计划通过前90分钟内的发生量预测后30分钟内的发生量
            break

    y, pred = np.array(y), np.array(pred)
    y = (m - n) * y + n
    pred = (m - n) * pred + n

    # 出图
    x = [i for i in range(len(y))]
    x_smooth = np.linspace(np.min(x), np.max(x), 1000)
    y_smooth = make_interp_spline(x, y)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='green', marker='*', ms=1, alpha=1, label='true')

    y_smooth = make_interp_spline(x, pred)(x_smooth)
    plt.plot(x_smooth, y_smooth, c='red', marker='o', ms=1, alpha=1, label='pred')
    plt.grid(axis='y')
    plt.legend()
    plt.show()


if __name__ == '__main__':
    Dtr, Val, Dte, m, n = load_data("4.csv")

    Dtr = process_data(Dtr, 5, False, m, n, 90)
    Val = process_data(Val, 5, False, m, n, 90)
    #Dte = process_data(Dte, 5, False, m, n, 90)

    Dte = process_data(Dte, 1, False, m, n, 90)

    train(Dtr, Val, "D:\\LIHAOWORK\\model.pth")
    #test(Dte, "D:\\LIHAOWORK\\model.pth", m, n)
    test_rolling(Dte, "D:\\LIHAOWORK\\model.pth", m, n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/552614.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

JRT在线初始化完善

之前实现的在线初始化留了个尾巴,那就是环境下载页构造zip包的时候没修改JRTBrowser的连接串地址为当前网站,这样就要求网站部署好之后给用户下载之前有人要把服务器的浏览器地址配置好。这样就增加一个运维工作,如果忘了或者不知道的人就会导…

基于SSM的计算机课程实验管理系统的设计与实现(内附设计LW + PPT+ 源码下载)

基于SSM的计算机课程实验管理系统的设计与实现 项目名称: 基于SSM的计算机课程实验管理系统的设计与实现 项目技术栈 该项目采用了以下核心技术栈: 后端框架/库: SSM (Spring Spring MVC MyBatis)数据库: MySQL前端技术&…

01 JavaScript学习 导读

什么是JavaScript? JavaScript 是一种用于创建交互式网页和网络应用程序的脚本语言。它是一种高级、动态类型的语言,广泛用于客户端网页开发,可以用来增强网页的交互性并实现各种功能。 以下是 JavaScript 的一些重要特点和用途:…

Linux中进程和计划任务

一.程序 1.什么是程序 (1)是一组计算机能识别和执行的指令,运行于电子计算机上,满足人们某种需求的信息化工具 (2)用于描述进程要完成的功能,是控制进程执行的指令集 二.进程 1.什么是进程…

ORAN C平面 Section Extension 23

ORAN C平面Section扩展23用于任意symbol模式的调制压缩参数。此section扩展允许为一个或多个“SymPrbPatterns”指定多组“mcScaleReMask、csf和mcScaleOffset”值。“SymPrbPattern”用于指定一组PRB,这些PRB可以跨越使用prbPattern指定的整个PRB范围(频…

20240329-1-SVM面试题

SVM面试题 1. SVM直观解释 SVM,Support Vector Machine,它是一种二分类模型,其基本模型定义为特征空间上的间隔最大的线性分类器,间隔最大使它有别于感知机;其还包括核技巧,这使它成为实质上的非线性分类…

ACID模型是什么

ACID模型是什么 ACID模型是数据库管理系统中保证事务处理安全性的一组特性。ACID是原子性(Atomicity)、一致性(Consistency)、隔离性(Isolation)和持久性(Durability)四个英文单词的…

使用 ECharts 绘制咖啡店各年订单的可视化分析

使用 ECharts 绘制咖啡店各年订单的可视化分析 在这篇博客中,我将分享一段使用 ECharts 库创建可视化图表的代码。通过这段代码,我们可以直观地分析咖啡店各年订单的情况。 饼图 这段代码包含了两个 ECharts 图表,一个是饼图,用…

lomobok源码编译学习笔记(1)

lomobok学习笔记(1) 项目导入 lombok的github地址 GitHub - projectlombok/lombok: Very spicy additions to the Java programming language. 开发工具 idea不知道为啥,装上ant工具也不好用,eclipse默认自带有ant,不需要装。…

matlab关于COE文件之读取操作

平台:matlab2021b 场景:在使用fir滤波器后,我们使用matlab生成coe文件后。在xilinx新建IP的后,数据流经过FIR的IP核后数据位宽变宽。这时候我们需要对数据进行截位。这时候需要读取coe文件求和后,计算我们需要截位的位…

Shell学习 - 2.27 Linux bc命令:一款数学计算器

Bash Shell 内置了对整数运算的支持,但是并不支持浮点运算,而 Linux bc 命令可以很方便的进行浮点运算,当然整数运算也不再话下。 bc是"Basic Calculator"的缩写。 bc 甚至可以称得上是一种编程语言了,它支持变量、数组…

初识ansible核心模块

目录 1、ansible模块 1.1 ansible常用模块 1.2 ansible-doc -l 列出当前anisble服务所支持的所有模块信息,按q退出 1.3 ansible-doc 模块名称 随机查看一个模块信息 2、运行临时命令 2.1 ansible命令常用的语法格式 3、常用模块详解与配置实例 3.1命令与…

RK3568驱动指南|第二篇 字符设备基础-第16章 一个驱动兼容不同设备实验

瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工…

PhotoShop2024安装包(亲测可用)

目录 一、软件简介 二、软件下载 一、软件简介 Adobe Photoshop是一款由Adobe Systems开发的图像编辑软件。它被广泛用于图像处理和数字艺术创作,是设计师、摄影师和艺术家们的首选工具之一。 主要功能: 图像编辑: Photoshop提供了丰富的编辑…

content-type对数据采集的影响,猿人学58题

在拿猿人学网站 https://www.python-spider.com/api/challenge58 练习的时候发现请求头中少了 content-type之后结果全部不对了 当我设置headers如下时 headers {# accept: application/json, text/javascript, */*; q0.01,content-type: application/x-www-form-urlencode…

【前端Vue】Vue从0基础完整教程第7篇:组件化开发,组件通信【附代码文档】

Vue从0基础到大神学习完整教程完整教程(附代码资料)主要内容讲述:vue基本概念,vue-cli的使用,vue的插值表达式,{{ gaga }},{{ if (obj.age > 18 ) { } }},vue指令,综合…

使用WebSocket实现答题积分排名实时更新的功能

需求分析 接到一个需求,是一个答题积分小程序,其中有一个功能需求是需要实时更新答题积分排名的。之前通常比较常见的需求,都是指定某个时间点才更新答题排行榜的数据的。 经过技术调研,要实现答题积分排名实时更新的功能&#…

基于SpringBoot+Vue的装饰工程管理系统(源码+文档+包运行)

一.系统概述 如今社会上各行各业,都喜欢用自己行业的专属软件工作,互联网发展到这个时候,人们已经发现离不开了互联网。新技术的产生,往往能解决一些老技术的弊端问题。因为传统装饰工程项目信息管理难度大,容错率低&a…

Word分节后,页码不连续、转PDF每节后多出空白页解决办法

1. 问题图例 废话少说,先上图: 2. 问题分析 问题分析:出现以上问题的原因可能有, 未链接到上一节页面布局中节的起始位置设置为[奇数页] 3. 解决问题 若为【1. 未链接到上一节】导致该问题出现,则我们需要选中页脚…

【Java开发指南 | 第十一篇】Java运算符

读者可订阅专栏:Java开发指南 |【CSDN秋说】 文章目录 算术运算符关系运算符位运算符逻辑运算符赋值运算符条件运算符(?:)instanceof 运算符Java运算符优先级 Java运算符包括:算术运算符、关系运算符、位运算符、逻辑运算符、赋值…