数学mathematics;代数:algebra ;
奇数:odd number 偶数:even number ;
分数:fraction 分子:numerator ;
分母:denominator 小数:decimal ;
负数:negative number 计算:calculate ;
加:plus /add减:minus/subtract ;
乘:multiply 除:divide ;
函数:function 平均值:average value ;
2024年09月08日
数学mathematics;代数:algebra ;
奇数:odd number 偶数:even number ;
分数:fraction 分子:numerator ;
分母:denominator 小数:decimal ;
负数:negative number 计算:calculate ;
加:plus /add减:minus/subtract ;
乘:multiply 除:divide ;
函数:function 平均值:average value ;
2024年09月08日
哈希表是一种键值映射的数据结构。哈希表中,数据以数组格式存储,其中每个数据值都有自己唯一的索引值,索引值通过哈希表的哈希函数计算得到。
2024年09月08日
发出一个固定金额的红包,由若干个人来抢,需要满足哪些规则?
1.所有人抢到金额之和等于红包金额,不能超过,也不能少于。
2.每个人至少抢到一分钱。
3.要保证所有人抢到金额的几率相等。
小灰的思路是什么样呢?
每次抢到的金额 = 随机区间 ( 0, 剩余金额 )
为什么这么说呢?让我们看一个栗子:
2024年09月08日
我考虑了一个简单的算法:
比如100元,由10个人分,那么平均一个人是10元钱。然后付款后,系统开始分份儿。
第一份:系统由0~10元之间随机一个数,作为这一份的钱数,设x1。
第二份:剩下的钱(100-x1),系统由0~(100-x1)/(10-1)随机一个数,作为这份的钱数,设x2
。。。
第n份:剩下的钱(100-x1-x2-...-xn),系统由0~(100-x1-x2-...-xn-1)/(10-n)随机一个数,作为这个份的钱数,设为xn
当用户进来拿红包的时候,系统由0~9之间随机一个数,随机到几,就取第几份红包,然后将这个数存到list里。当之后的用户抽到相同的随机数时,则将这个数+1,如遇相同再+1,直至list满,红包发完。
2024年09月08日
由于经常记不住stream的一些API每次要复制来复制去并且又长又臭,想要更加语意化的api,于是想到了以前写大数据Spark pandnas 等
2024年09月08日
随机红包算法,每个人都有自己的实现思路。
package com.jmmq.load.jim.algorithm;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
/**
* 红包算法
*/
public class RedPacketPrc {
private static final BigDecimal MIN = new BigDecimal("0.01");
public static void main(String[] args) {
String[] rs = redPacketRandom(new BigDecimal(1), 100, false);
BigDecimal sum = BigDecimal.ZERO;
for(String str: rs){
System.out.println(str);
sum = sum.add(new BigDecimal(str));
}
System.out.println("sum:" + sum);
System.out.println("(ˉ`?._.? ?._.?′ˉ)(ˉ`???′ˉ) (ˉ`?._.? ?._.?′ˉ)(ˉ`???′ˉ) (ˉ`?._.? ?._.?′ˉ)(ˉ`???′ˉ)");
String[] res = redPacketOpen(new BigDecimal(20), 6, false);
BigDecimal sum2 = BigDecimal.ZERO;
for(String str: res){
System.out.println(str);
sum2 = sum2.add(new BigDecimal(str));
}
System.out.println("sum2:" + sum2);
}
/**
*
* @param faceValue 面值 单位:元
* @param amount 人数
* @param avgFlag 是否平均
* @return
* 平均分就不写了
* 思路一:
* 按百分比进行随机计算,最后一个进行匝差计算
*/
public static String[] redPacketRandom(BigDecimal faceValue, int amount, boolean avgFlag){
// 先计算平均数 四舍五入
BigDecimal perValue = faceValue.divide(new BigDecimal(amount),3, BigDecimal.ROUND_HALF_UP);
// 平均下来最小的红包必须大于等于 1分钱
if(perValue.compareTo(MIN) == -1){
throw new RuntimeException("red packet amount OutOfBounds min = 0.01");
}
String[] rs = new String[amount];
// 平均
if(avgFlag){
// 这里四舍五入重新计算
perValue = faceValue.divide(new BigDecimal(amount),2, BigDecimal.ROUND_HALF_UP);
Arrays.fill(rs, perValue.toString());
// 无法除尽
if(perValue.multiply(new BigDecimal(amount)).compareTo(faceValue) != 0 ){
// 随机获取一个下标
int index = new Random().nextInt(amount);
rs[index] = String.valueOf(new BigDecimal(rs[index]).add(
faceValue.subtract(perValue.multiply(new BigDecimal(amount)))));
}
return rs;
}
BigDecimal weightSum = BigDecimal.ZERO;
BigDecimal redSum = BigDecimal.ZERO;
BigDecimal[] weights = new BigDecimal[amount];
// 随机
for (int i=0; i<rs.length; i++){
BigDecimal seed = new BigDecimal(new Random().nextInt(amount));
weightSum = weightSum.add(seed);
weights[i] = seed;
// 循环最后一个后计算金额
if(i == rs.length -1){
for(int j=0; j<rs.length; j++){
// 修改为向下取值,这样差额永远都是正数就不存在吃不掉差额的问题了
BigDecimal val = faceValue.multiply(weights[j].divide(weightSum,2, BigDecimal.ROUND_HALF_UP));
if(val.compareTo(MIN) == -1){
val = MIN;
}
redSum = redSum.add(val);
rs[j] = val.toString();
}
}
}
BigDecimal diff = faceValue.subtract(redSum);
if(faceValue.compareTo(redSum) != 0){
// 找到第一个加上或减少diff大于MIN的元素修改金额
for(int i=0; i<rs.length; i++){
if(new BigDecimal(rs[i]).add(diff).compareTo(MIN) > -1 ){
rs[i] = new BigDecimal(rs[i]).add(diff).toString();
break;
}
}
}
// 若没有任何一个元素能吃掉差额,因此差额需要进行分摊了,
// 这里简单粗暴的将循环到大于MIN的都改为MIN同时减少差额
// 这里代码不进行优化,会写另外一个优化的算法
if(faceValue.compareTo(redSum) != 0){
for(int i=0; i<rs.length; i++){
if(new BigDecimal(rs[i]).compareTo(MIN) > 0){
if(new BigDecimal(rs[i]).add(diff).compareTo(MIN) > -1){
rs[i] = new BigDecimal(rs[i]).add(diff).toString();
break;
} else {
diff.add(new BigDecimal(rs[i])).subtract(MIN);
rs[i] = MIN.toString();
}
}
}
}
return rs;
}
/**
* 上面算法进行优化
* @param faceValue 面值 单位:元
* @param amount 人数
* @param avgFlag 是否平均
* @return
* 优化思路:
* 上面算法为了保证红包最小金额处理上花费了大量的循环来处理
* 优化上就直接先分配最小金额,然后在进行随机分摊剩余的钱
*/
public static String[] redPacketOpen(BigDecimal faceValue, int amount, boolean avgFlag){
// 先计算平均数 四舍五入
BigDecimal perValue = faceValue.divide(new BigDecimal(amount),3, BigDecimal.ROUND_HALF_UP);
// 平均下来最小的红包必须大于等于 1分钱
if(perValue.compareTo(MIN) == -1){
throw new RuntimeException("red packet amount OutOfBounds min = 0.01");
}
String[] rs = new String[amount];
// 平均
if(avgFlag){
// 这里四舍五入重新计算
perValue = faceValue.divide(new BigDecimal(amount),2, BigDecimal.ROUND_HALF_UP);
Arrays.fill(rs, perValue.toString());
// 无法除尽
if(perValue.multiply(new BigDecimal(amount)).compareTo(faceValue) != 0 ){
// 随机获取一个下标
int index = new Random().nextInt(amount);
rs[index] = String.valueOf(new BigDecimal(rs[index]).add(
faceValue.subtract(perValue.multiply(new BigDecimal(amount)))));
}
return rs;
}
// 随机
// 先把低保放进去
Arrays.fill(rs, MIN.toString());
BigDecimal weightSum = BigDecimal.ZERO;
BigDecimal redSum = BigDecimal.ZERO;
BigDecimal[] weights = new BigDecimal[amount];
// 随机
for (int i=0; i<rs.length; i++){
BigDecimal seed = new BigDecimal(new Random().nextInt(amount));
weightSum = weightSum.add(seed);
weights[i] = seed;
// 循环最后一个后计算金额
if(i == rs.length -1){
for(int j=0; j<rs.length; j++){
BigDecimal val = faceValue.multiply(weights[j].divide(weightSum,2, BigDecimal.ROUND_DOWN));
redSum = redSum.add(val);
rs[j] = val.add(MIN).toString();
}
}
}
// 随机获取一个下标
BigDecimal diff = faceValue.subtract(redSum);
int index = new Random().nextInt(amount);
rs[index] = String.valueOf(new BigDecimal(rs[index]).add(diff));
return rs;
}
}
2024年09月08日
抢红包是一种在社交和支付应用中常见的互动活动,通常由一个人在某个特定场景(例如生日、节日、聚会等)下发一定数量的红包,其他参与者通过抢红包的方式获取红包中的随机金额,那么红包中的金额到底是如何随机生成的呢?下面我们就来看看一些场景的红包生成算法。
2024年09月08日
MiniExcel 是一个轻量级的 .NET 库,用于操作 Excel 文件。它支持创建、读取、修改和保存各种格式的 Excel 文件(如 .xlsx)。使用 MiniExcel 处理 Excel 文件的基本步骤通常包括引入库、使用提供的方法进行操作,然后保存或提取数据。以下是一些基础用法:
2024年09月08日
上一章,我们详细讲述了开发工具以及环境的搭建,并且成功输出了计算机的第一句语言“hello world!”。这一章我们开始还是先以这段程序为例,先看下图:
可以看到这段程序,主要包含以下部分:
1、 using System :using 关键字用于在程序中包含 System 命名空间,一个程序一般有多个 using 语句;
2024年09月08日
静态File类的常见的重要用法。
使用AppendAllLines()方法将多行文本添加到指定文件。
完整示例代码: