完成math.ch标准库(21个数学函数)
This commit is contained in:
parent
28b1639248
commit
fa706e2298
|
|
@ -1,228 +1,73 @@
|
|||
///! # 数学运算库
|
||||
///!
|
||||
///! Math Utilities
|
||||
///! 提供安全的数学运算函数
|
||||
///!
|
||||
///! **版本**: v1.0
|
||||
///! **模块**: charter-std/utils/math.ch
|
||||
|
||||
// ============================================================================
|
||||
// 安全算术运算
|
||||
// ============================================================================
|
||||
|
||||
/// 安全加法(检查溢出)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 第一个数
|
||||
/// - `b`: 第二个数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 和
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果发生溢出
|
||||
pub fn safe_add(a: u256, b: u256) -> u256 {
|
||||
let result = a + b;
|
||||
require(result >= a, "Addition overflow");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 安全减法(检查下溢)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 被减数
|
||||
/// - `b`: 减数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 差
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果发生下溢
|
||||
pub fn safe_sub(a: u256, b: u256) -> u256 {
|
||||
require(a >= b, "Subtraction underflow");
|
||||
return a - b;
|
||||
}
|
||||
|
||||
/// 安全乘法(检查溢出)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 第一个数
|
||||
/// - `b`: 第二个数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 积
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果发生溢出
|
||||
pub fn safe_mul(a: u256, b: u256) -> u256 {
|
||||
if a == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let result = a * b;
|
||||
require(result / a == b, "Multiplication overflow");
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 安全除法(检查除零)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 被除数
|
||||
/// - `b`: 除数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 商
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果除数为0
|
||||
pub fn safe_div(a: u256, b: u256) -> u256 {
|
||||
require(b > 0, "Division by zero");
|
||||
return a / b;
|
||||
}
|
||||
|
||||
/// 安全取模(检查除零)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 被除数
|
||||
/// - `b`: 除数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 余数
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果除数为0
|
||||
pub fn safe_mod(a: u256, b: u256) -> u256 {
|
||||
require(b > 0, "Modulo by zero");
|
||||
return a % b;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 比较函数
|
||||
// ============================================================================
|
||||
|
||||
/// 返回两个数中的最大值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 第一个数
|
||||
/// - `b`: 第二个数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 最大值
|
||||
pub fn max(a: u256, b: u256) -> u256 {
|
||||
return if a >= b { a } else { b };
|
||||
}
|
||||
|
||||
/// 返回两个数中的最小值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 第一个数
|
||||
/// - `b`: 第二个数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 最小值
|
||||
pub fn min(a: u256, b: u256) -> u256 {
|
||||
return if a <= b { a } else { b };
|
||||
}
|
||||
|
||||
/// 计算绝对差值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 第一个数
|
||||
/// - `b`: 第二个数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 绝对差值
|
||||
pub fn abs_diff(a: u256, b: u256) -> u256 {
|
||||
return if a >= b { a - b } else { b - a };
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 百分比和比例计算
|
||||
// ============================================================================
|
||||
|
||||
/// 计算百分比(使用基点,1基点 = 0.01%)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `amount`: 数量
|
||||
/// - `basis_points`: 基点(0-10000,10000 = 100%)
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 结果
|
||||
///
|
||||
/// # 示例
|
||||
/// ```
|
||||
/// let result = percentage(1000, 500); // 1000 * 5% = 50
|
||||
/// ```
|
||||
pub fn percentage(amount: u256, basis_points: u16) -> u256 {
|
||||
require(basis_points <= 10000, "Basis points must be <= 10000");
|
||||
return safe_mul(amount, basis_points as u256) / 10000;
|
||||
}
|
||||
|
||||
/// 计算比例
|
||||
///
|
||||
/// # 参数
|
||||
/// - `amount`: 数量
|
||||
/// - `numerator`: 分子
|
||||
/// - `denominator`: 分母
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 结果
|
||||
///
|
||||
/// # 示例
|
||||
/// ```
|
||||
/// let result = proportion(1000, 3, 4); // 1000 * 3/4 = 750
|
||||
/// ```
|
||||
pub fn proportion(amount: u256, numerator: u256, denominator: u256) -> u256 {
|
||||
require(denominator > 0, "Denominator cannot be zero");
|
||||
return safe_mul(amount, numerator) / denominator;
|
||||
}
|
||||
|
||||
/// 向上取整除法
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 被除数
|
||||
/// - `b`: 除数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 向上取整的商
|
||||
pub fn ceil_div(a: u256, b: u256) -> u256 {
|
||||
require(b > 0, "Division by zero");
|
||||
|
||||
if a == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (a - 1) / b + 1;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 幂运算
|
||||
// ============================================================================
|
||||
|
||||
/// 计算幂(a^b)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `base`: 底数
|
||||
/// - `exponent`: 指数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 结果
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果发生溢出
|
||||
pub fn pow(base: u256, exponent: u256) -> u256 {
|
||||
if exponent == 0 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
if base == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
let mut result: u256 = 1;
|
||||
let mut b = base;
|
||||
let mut e = exponent;
|
||||
|
||||
while e > 0 {
|
||||
if e % 2 == 1 {
|
||||
result = safe_mul(result, b);
|
||||
|
|
@ -230,247 +75,99 @@ pub fn pow(base: u256, exponent: u256) -> u256 {
|
|||
b = safe_mul(b, b);
|
||||
e = e / 2;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 计算平方根(整数部分)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `x`: 被开方数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 平方根的整数部分
|
||||
///
|
||||
/// # 算法
|
||||
/// 使用牛顿迭代法
|
||||
pub fn sqrt(x: u256) -> u256 {
|
||||
if x == 0 {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if x <= 3 {
|
||||
return 1;
|
||||
}
|
||||
|
||||
// 初始猜测值
|
||||
let mut z = x;
|
||||
let mut y = (x + 1) / 2;
|
||||
|
||||
// 牛顿迭代
|
||||
while y < z {
|
||||
z = y;
|
||||
y = (x / y + y) / 2;
|
||||
}
|
||||
|
||||
return z;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 平均值计算
|
||||
// ============================================================================
|
||||
|
||||
/// 计算算术平均值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `a`: 第一个数
|
||||
/// - `b`: 第二个数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 平均值
|
||||
pub fn average(a: u256, b: u256) -> u256 {
|
||||
// (a + b) / 2 可能溢出,使用 (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2)
|
||||
return (a / 2) + (b / 2) + ((a % 2 + b % 2) / 2);
|
||||
}
|
||||
|
||||
/// 计算加权平均值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `values`: 数值数组
|
||||
/// - `weights`: 权重数组
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 加权平均值
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果数组长度不匹配
|
||||
/// - 如果权重总和为0
|
||||
pub fn weighted_average(values: Vec<u256>, weights: Vec<u256>) -> u256 {
|
||||
require(values.len() == weights.len(), "Arrays length mismatch");
|
||||
require(values.len() > 0, "Arrays cannot be empty");
|
||||
|
||||
let mut sum: u256 = 0;
|
||||
let mut weight_sum: u256 = 0;
|
||||
|
||||
for i in 0..values.len() {
|
||||
sum = safe_add(sum, safe_mul(values[i], weights[i]));
|
||||
weight_sum = safe_add(weight_sum, weights[i]);
|
||||
}
|
||||
|
||||
require(weight_sum > 0, "Weight sum cannot be zero");
|
||||
|
||||
return sum / weight_sum;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 数组统计函数
|
||||
// ============================================================================
|
||||
|
||||
/// 计算数组总和
|
||||
///
|
||||
/// # 参数
|
||||
/// - `values`: 数值数组
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 总和
|
||||
pub fn sum(values: Vec<u256>) -> u256 {
|
||||
let mut result: u256 = 0;
|
||||
|
||||
for value in values {
|
||||
result = safe_add(result, value);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 查找数组最大值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `values`: 数值数组
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 最大值
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果数组为空
|
||||
pub fn array_max(values: Vec<u256>) -> u256 {
|
||||
require(values.len() > 0, "Array cannot be empty");
|
||||
|
||||
let mut max_value = values[0];
|
||||
|
||||
for value in values {
|
||||
if value > max_value {
|
||||
max_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
return max_value;
|
||||
}
|
||||
|
||||
/// 查找数组最小值
|
||||
///
|
||||
/// # 参数
|
||||
/// - `values`: 数值数组
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 最小值
|
||||
///
|
||||
/// # Panics
|
||||
/// - 如果数组为空
|
||||
pub fn array_min(values: Vec<u256>) -> u256 {
|
||||
require(values.len() > 0, "Array cannot be empty");
|
||||
|
||||
let mut min_value = values[0];
|
||||
|
||||
for value in values {
|
||||
if value < min_value {
|
||||
min_value = value;
|
||||
}
|
||||
}
|
||||
|
||||
return min_value;
|
||||
}
|
||||
|
||||
// ============================================================================
|
||||
// 金融计算函数
|
||||
// ============================================================================
|
||||
|
||||
/// 计算复利
|
||||
///
|
||||
/// # 参数
|
||||
/// - `principal`: 本金
|
||||
/// - `rate_basis_points`: 利率(基点,1基点 = 0.01%)
|
||||
/// - `periods`: 计息期数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 本息和
|
||||
///
|
||||
/// # 公式
|
||||
/// A = P * (1 + r)^n
|
||||
pub fn compound_interest(
|
||||
principal: u256,
|
||||
rate_basis_points: u16,
|
||||
periods: u256
|
||||
) -> u256 {
|
||||
pub fn compound_interest(principal: u256, rate_basis_points: u16, periods: u256) -> u256 {
|
||||
require(rate_basis_points <= 10000, "Rate must be <= 100%");
|
||||
|
||||
if periods == 0 {
|
||||
return principal;
|
||||
}
|
||||
|
||||
// 使用基点计算:(10000 + rate) / 10000
|
||||
let rate_factor = 10000 + (rate_basis_points as u256);
|
||||
let mut result = principal;
|
||||
|
||||
for _ in 0..periods {
|
||||
result = safe_mul(result, rate_factor) / 10000;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/// 计算单利
|
||||
///
|
||||
/// # 参数
|
||||
/// - `principal`: 本金
|
||||
/// - `rate_basis_points`: 利率(基点)
|
||||
/// - `periods`: 计息期数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u256`: 本息和
|
||||
///
|
||||
/// # 公式
|
||||
/// A = P * (1 + r * n)
|
||||
pub fn simple_interest(
|
||||
principal: u256,
|
||||
rate_basis_points: u16,
|
||||
periods: u256
|
||||
) -> u256 {
|
||||
pub fn simple_interest(principal: u256, rate_basis_points: u16, periods: u256) -> u256 {
|
||||
require(rate_basis_points <= 10000, "Rate must be <= 100%");
|
||||
|
||||
let interest = safe_mul(
|
||||
safe_mul(principal, rate_basis_points as u256),
|
||||
periods
|
||||
) / 10000;
|
||||
|
||||
let interest = safe_mul(safe_mul(principal, rate_basis_points as u256), periods) / 10000;
|
||||
return safe_add(principal, interest);
|
||||
}
|
||||
|
||||
/// 计算年化收益率(APY)
|
||||
///
|
||||
/// # 参数
|
||||
/// - `initial_value`: 初始价值
|
||||
/// - `final_value`: 最终价值
|
||||
/// - `days`: 天数
|
||||
///
|
||||
/// # 返回
|
||||
/// - `u16`: 年化收益率(基点)
|
||||
pub fn calculate_apy(
|
||||
initial_value: u256,
|
||||
final_value: u256,
|
||||
days: u256
|
||||
) -> u16 {
|
||||
pub fn calculate_apy(initial_value: u256, final_value: u256, days: u256) -> u16 {
|
||||
require(initial_value > 0, "Initial value must be positive");
|
||||
require(days > 0, "Days must be positive");
|
||||
|
||||
if final_value <= initial_value {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// APY = ((final / initial) - 1) * (365 / days) * 10000
|
||||
let gain = final_value - initial_value;
|
||||
let return_rate = safe_mul(gain, 10000) / initial_value;
|
||||
let apy = safe_mul(return_rate, 365) / days;
|
||||
|
||||
return min(apy, 10000) as u16;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue