分期利息计算——考虑免息日期和多利率设定的思路设计和代码实现

本文介绍了一种分期还款场景下的利息计算方法,重点在于处理不同阶段的利率变化、免息日及超额天数的利息计算。通过定义利率规则实体,利用循环遍历计算每一期的利息,确保了计算的准确性和灵活性。

前言

利息计算是一种常见的需求,尤其在现在这种分期还款场景比较常见的情况下。

需求描述

用户可以分期归还利息
多期,每一期利率不同,天数不同
利息计算以本金为基准,不设置利滚利
可以设置免息日,免息日内不计算利息
第一期和免息日起始时间是同一天
对于超于最后一个利率规则的天数按照最后一个利率规则计算利息

思路描述

1、为分期利率设置数据结构,比如第几期,利率,计息天数
2、使用循环遍历的方式判断
2.1、每一期内的计息天数
2.2、每一期内的免息天数
2.3、如果是最后一期,则需要考虑多余的天数也按照这个利率进行计算

代码实现
利率规则实体
import org.apache.commons.lang.builder.ToStringBuilder;
/**
 * 分期利率信息实体
 * @author jie.wu
 */
public class Rates{
	private int index;//第几阶段利率
	private int days;//本利率执行天数 比如 第1-10天,1%;第11-20天,2%;第21-30天,3%
	private String rates;//利率值
	public Rates(){}
	public Rates(int index,int days,String rates){
		this.index=index;
		this.days=days;
		this.rates=rates;
	}
	public int getIndex() {
		return index;
	}
	public void setIndex(int index) {
		this.index = index;
	}
	public int getDays() {
		return days;
	}
	public void setDays(int days) {
		this.days = days;
	}
	public String getRates() {
		return rates;
	}
	public void setRates(String rates) {
		this.rates = rates;
	}
	@Override
	public String toString() {
		return ToStringBuilder.reflectionToString(this);
	}
}
工具方法-计算第 j 阶段前(0到j-1)阶段一共几天

比如第一阶段10天,第二阶段10天,则第三阶段这个方法返回20

/**
	 * 计算本阶段之前一共有几天
	 * @param j
	 * @param ratesArray
	 * @return
	 */
	private static int getForeDays(int j,Rates[] ratesArray){
		int foreDays=0;
		for(int i=0;i<j;i++){
			foreDays+=ratesArray[i].getDays();
		}
		return foreDays;
	}
  • 计算第 j 阶段需要计算的利息天数

需要考虑免息日的情况

/**
	 * 计算第 j 阶段需要计算利息的天数
	 * 对于垫资天数超过所有设定阶段天数总和的,多余的天数按照最后一个利率进行计算
	 * @param j   第几阶段-从0计数
	 * @param freeDays   免息日
	 * @param fullDays   总垫资日
	 * @param ratesArray 利率设定数组
	 * @return 
	 */
	private static BigDecimal getTemDays(int j,int freeDays,int fullDays,Rates[] ratesArray){
		//如果是第一阶段
		if(j==0){
			//本阶段减去免息日
			//如果为正值则取该值
			//如果为负值,则本阶段不计算利息
			return new BigDecimal(ratesArray[j].getDays()-freeDays>0?ratesArray[j].getDays()-freeDays:0);
		}
		
		//如果是最后一个阶段
		if(j==ratesArray.length-1){
			//计算之前几个阶段的天数和-不包括本阶段
			int foreDays=getForeDays(j,ratesArray);
			
			//计算本阶段以及之后阶段免息日天数
			int temfreeDays=freeDays-foreDays>0?freeDays-foreDays:0;
			
			//计算本阶段垫资的天数
			int temDays=fullDays-foreDays>0?fullDays-foreDays:0;
			
			//将本阶段之后的天数也作为本阶段来考虑
			
			//将本阶段免息日期考虑进来
			temDays=temDays-temfreeDays>0?temDays-temfreeDays:0;
			return new BigDecimal(temDays);
		}else{
			//计算之前几个阶段的天数和-不包括本阶段
			int foreDays=getForeDays(j,ratesArray);
			
			//计算本阶段以及之后阶段免息日天数
			int temfreeDays=freeDays-foreDays>0?freeDays-foreDays:0;
			
			//计算本阶段垫资的天数
			int temDays=fullDays-foreDays>0?fullDays-foreDays:0;
			//考虑总垫资天数超过本阶段的情况,则本阶段仅取本阶段的天数
			if(temDays>ratesArray[j].getDays()){
				temDays=ratesArray[j].getDays();
			}
			
			//将本阶段免息日期考虑进来
			temDays=temDays-temfreeDays>0?temDays-temfreeDays:0;
			return new BigDecimal(temDays);
		}
	}
测试方法
@Test
	public void testMethod(){
		long beginDate=new Date().getTime();
		//今天距离垫资日天数
		int fullDays=987;
		//免息日为 3 天
		int freeDays=2;
		//本金
		BigDecimal principal=new BigDecimal("100");
		//分期利率规则 json 字符串
		String arrayStr="[{\"days\":10,\"index\":1,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":2,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":3,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":4,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":5,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":6,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":7,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":8,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":9,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":10,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":11,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":12,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":13,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":14,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":15,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":16,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":17,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":18,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":19,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":20,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":21,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":22,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":23,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":24,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":25,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":26,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":27,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":28,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":29,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":30,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":31,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":32,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":33,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":34,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":35,\"rates\":\"0.01\"},"
				+ "{\"days\":10,\"index\":36,\"rates\":\"0.01\"}]";
		
		//将字符串转化为 JSONArray 对象
		JSONArray array=JSONArray.fromObject(arrayStr);
		
		//数组长度
		int size=array.size();
		Rates[] ratesArray=new Rates[size];
		
		//按照排序将利率存放到数组
		for(int i=0;i<array.size();i++){
			Rates rates=(Rates)JSONObject.toBean((JSONObject) array.get(i),Rates.class);
			ratesArray[rates.getIndex()-1]=rates;
		}
		
		//程序运行到这里,利率已经按照先后顺序排列好了
		
		//利息总金额
		BigDecimal sumInterest=new BigDecimal("0");
		
		for(int j=0;j<ratesArray.length;j++){
			//都只计算本阶段都利率
			//现在是第 j 阶段
			System.out.print("现在是第"+j+"阶段;");
			//计算借款天数在本阶段借款天数-需要考虑免息日第情况
			//如果是最后一个利率阶段,垫资天数还在延续,则将多余天数计算到最后一个利率中
			BigDecimal temDays=getTemDays(j,freeDays,fullDays,ratesArray);
			//本阶段的利息
			BigDecimal temInterest=new BigDecimal("0");
			temInterest=new BigDecimal(ratesArray[j].getRates()).multiply(temDays).multiply(principal);
			System.out.println("本阶段的利息为:"+temInterest);
			sumInterest=sumInterest.add(temInterest);
		}
		
		long endDate=new Date().getTime();
		System.out.println("最后利息总额:"+sumInterest+";耗时:"+(endDate-beginDate));
		
	}
<think>我们正在设计一个基于模态生理信号的睡眠分期自动检测系统。这个任务通常涉及到信号处理、特征提取机器学习或深度学习模型。以下是一个简化的代码框架,展示如何实现这样的系统。由于完整实现非常复杂,这里只提供一个概念性的代码结构。 步骤: 1. 数据加载:加载模态生理信号数据(如EEG, EOG, EMG等)。 2. 预处理:包括滤波、去噪、分段等。 3. 特征提取:从每个分段中提取时域、频域非线性特征。 4. 特征选择(可选):选择最有判别力的特征。 5. 模型训练:使用分类算法(如随机森林、SVM或深度学习模型)进行训练。 6. 评估:评估模型性能。 注意:实际应用中,深度学习模型(如CNN、LSTM或它们的组合)可以直接从原始信号中学习特征,从而跳过手工特征提取步骤。 下面是一个简化的示例代码,使用手工特征随机森林分类器: ```python import numpy as np import pandas as pd from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report # 1. 加载数据(假设数据已经预处理并存储在CSV中,每行是一个样本,包括特征标签) # 假设数据文件:'sleep_data.csv',包含特征列最后的'stage'列(标签) data = pd.read_csv('sleep_data.csv') X = data.drop('stage', axis=1).values y = data['stage'].values # 2. 划分训练集测试集 X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42) # 3. 创建模型 model = RandomForestClassifier(n_estimators=100, random_state=42) # 4. 训练模型 model.fit(X_train, y_train) # 5. 预测 y_pred = model.predict(X_test) # 6. 评估 print("准确率: ", accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred)) ``` 对于深度学习模型,我们可以使用CNN处理信号(假设信号已经被分割成固定长度的片段): ```python import tensorflow as tf from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense, Dropout # 假设输入是形状为 (n_samples, n_timesteps, n_channels) 的3D数组 # 例如:100个样本,每个样本3000个时间点,3个通道(EEG, EOG, EMG) # 构建模型 model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(3000, 3))) model.add(Conv1D(filters=64, kernel_size=3, activation='relu')) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(5, activation='softmax')) # 假设有5个睡眠阶段 model.compile(loss='sparse_categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # 训练模型(假设X_trainy_train已经准备好) model.fit(X_train, y_train, epochs=10, batch_size=32, validation_split=0.1) ``` 注意:实际应用中,需要更复杂的网络结构(如使用LSTM或混合模型)以及更细致的数据预处理。 §§相关问题§§ 1. 模态生理信号睡眠分期中常用的信号有哪些? 2. 在预处理阶段,针对EEG、EOGEMG信号通常会进行哪些处理? 3. 除了随机森林CNN,还有哪些机器学习或深度学习方法适用于睡眠分期? 4. 如何评估睡眠分期模型的性能?有哪些常用的评价指标? 5. 如何处理睡眠数据中的类别不平衡问题? </think>### 基于模态生理信号的睡眠分期自动检测系统设计实现 睡眠分期检测系统通常需要处理EEG(脑电)、EOG(眼电)、EMG(肌电)等信号,核心流程包括数据预处理、特征提取、模型训练预测。以下是关键代码模块的简化实现: #### 1. 信号预处理(滤波与分段) ```python import numpy as np from scipy.signal import butter, filtfilt def preprocess_signal(signal, fs=256): """模态信号预处理:带通滤波 + 分段""" # 设计4-30Hz带通滤波器(适用于EEG/EOG) b, a = butter(4, [4/(fs/2), 30/(fs/2)], btype='bandpass') filtered = filtfilt(b, a, signal) # 分段:30秒为一期(睡眠分期标准) epoch_length = 30 * fs # 30秒*采样率 epochs = [filtered[i:i+epoch_length] for i in range(0, len(filtered), epoch_length)] return np.array(epochs) ``` #### 2. 模态特征提取 ```python from scipy.stats import entropy from pyentrp import sample_entropy as sampen def extract_features(eeg, eog, emg): """从三通道信号中提取时频域特征""" features = [] for sig, name in zip([eeg, eog, emg], ['EEG','EOG','EMG']): # 时域特征 mean = np.mean(sig) std = np.abs(sig).std() # 频域特征:δ(0.5-4Hz), θ(4-8Hz), α(8-13Hz), β(13-30Hz)功率比 freqs = np.fft.rfftfreq(len(sig), 1/256) psd = np.abs(np.fft.rfft(sig))**2 band_powers = [] for band in [(0.5,4), (4,8), (8,13), (13,30)]: mask = (freqs>=band[0]) & (freqs<=band[1]) band_powers.append(np.sum(psd[mask])) total_power = np.sum(psd) rel_powers = [bp/total_power for bp in band_powers] # 非线性特征 samp_en = sampen.sample_entropy(sig, 2, 0.2*np.std(sig)) features.extend([mean, std, *rel_powers, samp_en]) return np.array(features) ``` #### 3. 深度学习模型(CNN-LSTM) ```python from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv1D, LSTM, Dense, Dropout def build_model(input_shape, n_classes=5): """混合神经网络架构:CNN提取空间特征 + LSTM捕捉时序依赖""" model = Sequential([ # 卷积层处理局部模式 Conv1D(64, kernel_size=3, activation='relu', input_shape=input_shape), Conv1D(128, kernel_size=3, activation='relu'), # LSTM捕获长时序关系 LSTM(64, return_sequences=True), LSTM(32), # 输出睡眠分期:W, N1, N2, N3, REM Dense(128, activation='relu'), Dropout(0.5), Dense(n_classes, activation='softmax') ]) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) return model # 使用示例 # model = build_model(input_shape=(7680, 3)) # 30秒*256Hz, 三通道 # model.fit(X_train, y_train_onehot, epochs=50) ``` #### 4. 模型评估 ```python from sklearn.metrics import confusion_matrix, cohen_kappa_score def evaluate_model(y_true, y_pred): """输出睡眠分期关键评估指标""" cm = confusion_matrix(y_true, y_pred) kappa = cohen_kappa_score(y_true, y_pred) stage_acc = cm.diagonal() / cm.sum(axis=1) # 各分期单独准确率 print(f"Overall Accuracy: {np.mean(y_true==y_pred):.3f}") print(f"Cohen's Kappa: {kappa:.3f}") print("Per-class Accuracy:") for i, acc in enumerate(["Wake", "N1", "N2", "N3", "REM"]): print(f" {acc}: {stage_acc[i]:.3f}") return cm ``` ### 系统实现要点 1. **数据来源**:推荐使用公开数据集(如Sleep-EDF) 2. **特征工程**:可加入Hjorth参数、分形维度等非线性特征 3. **类别平衡**:对稀有的N1期使用过采样技术 4. **实时部署**:通过TensorFlow Lite转换为嵌入式设备可运行模型 > **注意**:完整系统需包含数据标注工具(符合AASM标准)、可视化模块及临床验证流程。实际准确率可达87%以上(Cohen's Kappa >0.8)。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值