Unicode 联盟(Unicode Consortium) Unicode 联盟(Unicode Consortium)开发了 Unicode 标准(Unicode Standard)。他们的目标是使用标准的 Unicode 转换格式(即 UTF,全称 Unicode Transformation Format)取代现有的字符集。
2024年04月09日
Unicode 联盟(Unicode Consortium) Unicode 联盟(Unicode Consortium)开发了 Unicode 标准(Unicode Standard)。他们的目标是使用标准的 Unicode 转换格式(即 UTF,全称 Unicode Transformation Format)取代现有的字符集。
2024年04月09日
该文章主要介绍JDK中各种常见的函数式接口,并会附上一些个人对函数式编程的一些扩展思考与实际用法。 jdk1.8的函数式接口都在rt.jar中java.util.function包下,以下以jdk集合类与个人常用的接口进行介绍:前言
常见的函数式接口介绍
2024年04月09日
Ohos-MaterialRefreshLayout是一个自定义Material风格下拉刷新控件,支持设置水波纹效果,支持下拉刷新侵入式和非侵入式,初始化自动刷新及上滑加载更多,支持刷新头部自定义图案,上拉加载更多等。该控件一般配合ListContainer使用,因涉及事件分发操作,本库中使用了三方控件NestedListContainer、事件分发等方便处理事件拦截分发事件。介绍
2024年04月09日
今天正忙的焦头烂额,领导突然问我为啥他写的代码50 减去0等于 0? 头上冒出三条黑线,作为领导你还真是啥奇葩问题都能遇到 小女不才,给出以下方法
2024年04月09日
14年微信推出红包功能以后,很多公司开始上自己的红包功能,到现在为止仍然有很多红包开发的需求,实现抢红包算法也是面试常考题。 要求:概述
2024年04月09日
在我作为技术面试官的这么多年时间里,我发现大部分Java程序员都会忽略的几个问题,虽然说这些问题不“致命“,但确实会降低面试分,因此,今天总结分享出来,希望大家能够引以为戒。
2024年04月09日
在我们日常工作中数值计算是不可避免的,特别是电商类系统中,这个问题一般情况下我们都是特别注意的,但是一不注意就会出大问题,跟钱有关的事情没小事。这不新来的大兄弟就一个不注意,在这个小阴沟里翻车了,闹笑话了。 为了我们以后可以避免在这个问题上犯错,我今天特地写了这一篇来总结一下。
2024年04月09日
随机红包算法,每个人都有自己的实现思路。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;
}
}