【面试场景题】随机立减金额计算

文章目录

  • 背景
  • 设计思路
  • 方案
  • 结论
  • 高斯分布(正态分布)

背景

某电商公司跟某银行有合作,推进银行信用卡办卡&流水,使用此银行信用卡用户,支付可以随机立减10~30元。其实公司每一笔都可获得30元支付立减金,所以,老板希望用户获取的立减金统计平均值约等于15元,这样相当于公司每一笔支付都能赚15元。

设计思路

1)需要随机立减,所以需要一个随机数算法。
2)需要有统计平均数,使得平均立减金额约等于15元

方案

(一)加权随机算法

原理:为不同金额区间分配不同的权重,金额越小权重越高
优势:可以精确控制每个金额的出现概率,容易理解和调整
实现:预定义金额值和对应权重,根据权重随机选择

(二)随机数池

原理:预先生成一个符合要求的随机数集合,使用时从中随机抽取
优势:保证整体分布符合预期,性能较好
实现:按比例生成不同区间的数值,然后打乱顺序存储在池中

(三)高斯分布(正态分布)算法

原理:利用正态分布特性,设置合适的均值和标准差
优势:数学理论基础扎实,分布自然
实现:使用Random.nextGaussian()生成正态分布随机数,映射到目标区间

另外三种方案是通义灵码默认生成的方案。

#file:/Users/liunian/IdeaProjects/study/src/main/java/org/example/random/PayCutAmount.java
package org.example.random;import java.util.*;/*** 支付立减金额计算类* 实现一个随机算法,使立减金额在10-30元之间,平均值约为15元*/
public class PayCutAmount {private static final Random random = new Random();// ==================== 方案1:三角分布数池 ====================/*** 计算支付立减金额 - 三角分布方法* 算法目标:在10-30元范围内生成随机立减金额,长期平均值约为15元** @return 立减金额(单位:元)*/public static double calculateCutAmount() {// 使用三角分布来实现期望值为15的随机数// 三角分布公式:min + (max - min) * (sqrt(r1 * r2))// 其中r1和r2是两个0-1之间的随机数double min = 10.0;double max = 30.0;// 方法1:使用三角分布(推荐)double r1 = random.nextDouble();double r2 = random.nextDouble();double cutAmount = min + (max - min) * Math.sqrt(r1 * r2);// 确保结果在范围内return Math.max(min, Math.min(max, cutAmount));}// ==================== 方案2:简单线性分布 ====================/*** 简单线性分布方法(备选)* 使用平方根方法来偏向较小值** @return 立减金额(单位:元)*/public static double calculateCutAmountSimple() {double min = 10.0;double max = 30.0;// 使用平方根来创建偏向小值的分布double r = Math.sqrt(random.nextDouble());return min + (max - min) * r;}// ==================== 方案3:Beta分布 ====================/*** 基于Beta分布的方法* 通过调整α和β参数来控制分布形状** @return 立减金额(单位:元)*/public static double calculateCutAmountBeta() {double min = 10.0;double max = 30.0;// Beta分布参数,α<1, β>1 使得分布左偏double alpha = 0.8;double beta = 1.5;// 简化的Beta分布采样double x = Math.pow(random.nextDouble(), 1/alpha);double y = Math.pow(random.nextDouble(), 1/beta);double betaValue = x / (x + y);return min + (max - min) * betaValue;}// ==================== 方案4:加权平均算法 ====================/*** 加权平均算法实现* 通过为不同金额区间设置不同的权重来控制平均值* * @return 立减金额(单位:元)*/public static double calculateByWeightedAverage() {// 定义金额区间和对应的权重// 为了使平均值接近15,给较小金额更高权重double[] amounts = {10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30};double[] weights = {11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1}; // 权重递减// 计算总权重double totalWeight = 0;for (double weight : weights) {totalWeight += weight;}// 生成随机数并根据权重选择金额double randomValue = random.nextDouble() * totalWeight;double cumulativeWeight = 0;for (int i = 0; i < amounts.length; i++) {cumulativeWeight += weights[i];if (randomValue <= cumulativeWeight) {return amounts[i];}}// 理论上不会到达这里return amounts[amounts.length - 1];}// ==================== 方案5:随机数池 ====================// 随机数池,预先生成符合要求的数值private static final List<Double> randomPool = generateRandomPool();/*** 生成随机数池* 预先生成一组符合平均值要求的随机数* * @return 随机数池*/private static List<Double> generateRandomPool() {List<Double> pool = new ArrayList<>();Random rand = new Random();// 生成200个随机数,其中大部分是较小值,少量是较大值// 保证整体平均值约为15for (int i = 0; i < 120; i++) {// 生成10-17之间的数(占比60%)double value = 10 + rand.nextDouble() * 7;pool.add(Math.round(value * 100.0) / 100.0); // 保留两位小数}for (int i = 0; i < 60; i++) {// 生成17-24之间的数(占比30%)double value = 17 + rand.nextDouble() * 7;pool.add(Math.round(value * 100.0) / 100.0);}for (int i = 0; i < 20; i++) {// 生成24-30之间的数(占比10%)double value = 24 + rand.nextDouble() * 6;pool.add(Math.round(value * 100.0) / 100.0);}// 打乱顺序Collections.shuffle(pool, rand);return pool;}/*** 从随机数池中获取随机立减金额* * @return 立减金额(单位:元)*/public static double calculateFromRandomPool() {int index = random.nextInt(randomPool.size());return randomPool.get(index);}// ==================== 方案6:高斯正态分布 ====================/*** 高斯正态分布算法实现* 使用正态分布生成随机数,然后映射到目标区间* * @return 立减金额(单位:元)*/public static double calculateByGaussian() {// 设置期望值和标准差// 为了让平均值接近15,我们设置期望值略小于15double mean = 14.5;  // 期望值double stdDev = 4.0; // 标准差// 生成正态分布的随机数double gaussianValue = random.nextGaussian() * stdDev + mean;// 将结果限制在10-30范围内gaussianValue = Math.max(10, Math.min(30, gaussianValue));// 保留两位小数return Math.round(gaussianValue * 100.0) / 100.0;}/*** 测试方法:验证所有算法的平均值是否接近15元*/public static void main(String[] args) {int testCount = 100000;double sum1 = 0, sum2 = 0, sum3 = 0, sum4 = 0, sum5 = 0, sum6 = 0;System.out.println("测试" + testCount + "次随机立减金额算法:");System.out.println("================================");// 测试三角分布方法for (int i = 0; i < testCount; i++) {double amount = calculateCutAmount();sum1 += amount;}double average1 = sum1 / testCount;System.out.println("三角分布方法:");System.out.println("  平均立减金额: " + String.format("%.2f", average1) + "元");System.out.println("  与目标值15元的偏差: " + String.format("%.4f", Math.abs(15 - average1)) + "元");// 测试简单线性分布方法for (int i = 0; i < testCount; i++) {double amount = calculateCutAmountSimple();sum2 += amount;}double average2 = sum2 / testCount;System.out.println("简单线性分布方法:");System.out.println("  平均立减金额: " + String.format("%.2f", average2) + "元");System.out.println("  与目标值15元的偏差: " + String.format("%.4f", Math.abs(15 - average2)) + "元");// 测试Beta分布方法for (int i = 0; i < testCount; i++) {double amount = calculateCutAmountBeta();sum3 += amount;}double average3 = sum3 / testCount;System.out.println("Beta分布方法:");System.out.println("  平均立减金额: " + String.format("%.2f", average3) + "元");System.out.println("  与目标值15元的偏差: " + String.format("%.4f", Math.abs(15 - average3)) + "元");// 测试加权平均算法for (int i = 0; i < testCount; i++) {double amount = calculateByWeightedAverage();sum4 += amount;}double average4 = sum4 / testCount;System.out.println("加权平均算法:");System.out.println("  平均立减金额: " + String.format("%.2f", average4) + "元");System.out.println("  与目标值15元的偏差: " + String.format("%.4f", Math.abs(15 - average4)) + "元");// 测试随机数池方法for (int i = 0; i < testCount; i++) {double amount = calculateFromRandomPool();sum5 += amount;}double average5 = sum5 / testCount;System.out.println("随机数池方法:");System.out.println("  平均立减金额: " + String.format("%.2f", average5) + "元");System.out.println("  与目标值15元的偏差: " + String.format("%.4f", Math.abs(15 - average5)) + "元");// 测试高斯正态分布方法for (int i = 0; i < testCount; i++) {double amount = calculateByGaussian();sum6 += amount;}double average6 = sum6 / testCount;System.out.println("高斯正态分布方法:");System.out.println("  平均立减金额: " + String.format("%.2f", average6) + "元");System.out.println("  与目标值15元的偏差: " + String.format("%.4f", Math.abs(15 - average6)) + "元");}
}

运行结果

测试100000次随机立减金额算法:
================================
三角分布方法:平均立减金额: 18.86元与目标值15元的偏差: 3.8631元
简单线性分布方法:平均立减金额: 23.32元与目标值15元的偏差: 8.3199Beta分布方法:平均立减金额: 18.12元与目标值15元的偏差: 3.1212元
加权平均算法:平均立减金额: 16.65元与目标值15元的偏差: 1.6520元
随机数池方法:平均立减金额: 17.21元与目标值15元的偏差: 2.2119元
高斯正态分布方法:平均立减金额: 14.77元与目标值15元的偏差: 0.2299

结论

可以看出,高斯正态分布的结果是最接近15元的,线性、三角分布、beta分布的结果与15元都相差不小,如果不想通过记录统计每一个立减的值来算出平均值,高斯分布是最合适的算法。

高斯分布(正态分布)

正态分布(Normal distribution),又称为常态分布或高斯分布,通常记作X~N(μ ,σ2)。其中, μ是正态分布的数学期望(均值), σ2是正态分布的方差。μ = 0,σ = 1的正态分布被称为标准正态分布 。
正态分布的概率密度函数显示为典型的钟形曲线,这一形状类似于寺庙中的大钟,因此也常被称为钟形曲线。作为一种连续分布,正态分布拥有完备的概率密度函数、累积分布函数、矩生成函数和特征函数等表达形式,并且具备明确的期望(即均值)、方差、偏度和峰度等数值特征。中心极限定理阐述了在一定条件下,多个独立同分布的随机变量的平均值会趋向于正态分布,这一现象在样本量增大时尤为显著。
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2025年湖北中级注册安全工程师报考那些事

2025年湖北中级注册安全工程师报考那些事各位从事建筑安全的人员看过来&#xff0c;注册安全工程师是你们行业认可度较为高的证书。关于报考无论是安全相关专业跟不相关的专业都是可以报考的。只是年份要求不同。 本科&#xff1a;相关专业3年&#xff0c;不相关专业4年。 专科…

Prometheus + Grafana + Micrometer 监控方案详解

这套组合是当前Java生态中最流行的监控解决方案之一&#xff0c;特别适合云原生环境下的微服务应用监控。下面我将从技术实现到最佳实践进行全面解析。 一、技术栈组成与协作 1. 组件分工组件角色关键能力Micrometer应用指标门面(Facade)统一指标采集API&#xff0c;对接多种监…

实习小记(个人中心的编辑模块)

实习小记&#xff08;个人中心的编辑模块&#xff09; 项目需要加一个个人中心的编辑模块&#xff0c;也是差不多搞了一天下来&#xff0c;其中遇到了很多问题&#xff0c;也是来记录、分享一下。 技术栈&#xff1a;React、antd、TypeScript 需求 点击编辑&#xff0c;弹出编…

【7】串口编程三种模式(查询/中断/DMA)韦东山老师学习笔记(课程听不懂的话试着来看看我的学习笔记吧)

<1>前置概念补充在深入拆解三种模式前&#xff0c;先通过提供的 “函数对比表” 建立整体认知&#xff1a;这张表是串口收发的「武器库索引」&#xff0c;清晰标注了查询、中断、DMA 三种模式下&#xff0c;收发 / 回调函数的对应关系。后续会结合实际代码&#xff0c;讲…

【Kubernetes 指南】基础入门——Kubernetes 201(二)

二、滚动升级- 滚动升级&#xff08;Rolling Update&#xff09;通过逐个容器替代升级的方式来实现无中断的服务升级&#xff1a;- 在滚动升级的过程中&#xff0c;如果发现了失败或者配置错误&#xff0c;还可以随时回滚&#xff1a;- 需要注意的是&#xff0c; kubectl rolli…

网络资源模板--基于Android Studio 实现的图书商城App

目录 一、测试环境说明 二、项目简介 三、项目演示 四、部设计详情&#xff08;部分) 登录注册页 首页 五、项目源码 一、测试环境说明 电脑环境 Windows 11 编写语言 JAVA 开发软件 Android Studio (2020) 开发软件只要大于等于测试版本即可(近几年官网直接下载…

JavaWeb 进阶:Vue.js 与 Spring Boot 全栈开发实战(Java 开发者视角)

作为一名 Java 开发工程师&#xff0c;当你掌握了 HTML、CSS 和 JavaScript 的基础后&#xff0c;是时候接触现代前端框架了。Vue.js 以其简洁的 API、渐进式的设计和优秀的中文文档&#xff0c;成为众多 Java 开发者入门前端框架的首选。Vue.js 让你能快速构建响应式、组件化的…

智能体产品化的关键突破:企业智能化转型的“最后一公里”如何迈过?

智能体产品化的关键突破&#xff1a;企业智能化转型的“最后一公里”如何迈过&#xff1f; 在人工智能迅猛发展的当下&#xff0c;智能体&#xff08;Agent&#xff09;成为企业数字化转型的新引擎。无论是市场分析、客户服务&#xff0c;还是自动化办公&#xff0c;智能体都被…

Rust × Elasticsearch官方 `elasticsearch` crate 上手指南

1 为什么选择官方 Rust 客户端&#xff1f; 语义化兼容&#xff1a;客户端 主版本 与 ES 主版本 严格对应&#xff0c;8.x 客户端可对接任何 8.x 服务器&#xff1b;不存在跨主版本兼容承诺 (docs.rs)100% API 覆盖&#xff1a;稳定 API 全量映射&#xff0c;Beta/实验特性可按…

怎样画流程图?符号与流程解构教程

在数字化办公和项目管理日益复杂的当下&#xff0c;流程图早已不是工程师、项目经理的专属工具&#xff0c;它正快速成为每一位职场人提升表达效率、理清工作逻辑的利器。无论是软件开发中的流程规范、产品设计阶段的用户路径&#xff0c;还是企业内部的审批流程、团队协作机制…

vue3 + vite || Vue3 + Webpack创建项目

1.vue3 vite搭建项目方法 &#xff08;需要提前装node,js&#xff09; 1. 使用官方 create-vite 工具&#xff08;推荐&#xff09; 1.使用npm----------------------------- npm create vuelatest2.使用pnpm----------------------------- pnpm create vuelatest3.使用yarn--…

Vue2-封装一个含所有表单控件且支持动态增减行列的表格组件

效果1. 无编辑权限&#xff1a;显示普通表格2. 有编辑权限&#xff1a;根据配置显示编辑控件3. 可以动态新增行&#xff0c;也可以动态新增列 核心代码无权限情况的核心代码<!-- 无编辑权限时显示普通表格 --><el-tablev-if"!hasEditPermission"ref"ta…

网络原理 - TCP/IP(一)

目录 1. 应用层&#xff1a;用户与网络的 “交互窗口” 1.1 应用层协议&#xff1a;规范交互的 “通用语言” 1.2 自定义协议&#xff1a;适配特殊需求的 “专属规则” 1.3 应用层数据格式&#xff1a;让数据 “说得明白” 1.3.1 XML&#xff1a;结构化但繁琐的 “老…

Orange的运维学习日记--16.Linux时间管理

Orange的运维学习日记–16. Linux时间管理 文章目录Orange的运维学习日记--16. Linux时间管理系统与硬件时钟时钟类型对比查看内核支持的时钟源本地时间调整使用 date 查看与设置一次性同步&#xff1a;ntpdate同步到硬件时钟&#xff1a;hwclock基于 systemd 的 timedatectl交…

Git 与 GitHub 的对比与使用指南

Git 与 GitHub 的对比与使用指南 在软件开发中&#xff0c;Git 和 GitHub 是两个密切相关但本质不同的工具。下面我将逐步解释它们的定义、区别、核心概念以及如何协同使用&#xff0c;确保内容真实可靠&#xff0c;基于广泛的技术实践。 1. 什么是 Git&#xff1f; Git 是一个…

20250726-4-Kubernetes 网络-Service DNS名称解析_笔记

一、Service DNS名称 1. 例题:通信需求 通信场景:项目A中的Pod需要与项目B中的Pod进行通信,直接使用Pod IP不可行,因为Pod IP会随着Pod生命周期变化。 解决方案:通过Service提供的稳定IP地址进行通信,不受Pod重建、扩容/缩容等操作影响。 2. CoreDNS介绍  基本功能…

vscode 登录ssh记住密码直接登录设置

第一种情况在系统已经生成密钥对的情况下&#xff1a;点击这里的设置第二步&#xff1a;第三步&#xff1a;没有填写的给填写一下第四步骤&#xff1a;保存后进入选择这个点开第五步&#xff1a;去Linux终端下输入这个命令就OK了echo "ssh-rsa内容" >> ~/.ssh/…

Nginx 动静分离配置(详细版)

本文介绍了Nginx 动静分离相关配置&#xff0c;主要包括了配置文件创建、配置示例、配置原理解析以及重新启用配置文件等等 本文目录1. 创建 Nginx 配置文件2. 配置示例3. 配置原理解析4. 启用配置文件并重新加载 Nginx1. 创建 Nginx 配置文件 在 /etc/nginx/sites-available …

C# CAN通信上位机系统设计与实现

C# CAN通信上位机系统设计与实现 C# CAN通信上位机程序&#xff0c;支持多种CAN适配器&#xff0c;提供数据收发、协议解析、数据可视化等功能。 using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; usi…

Ubuntu20.04子系统

常用 # 导出分发版到 E盘 wsl --export Ubuntu-20.04 E:\wsl-ubuntu20.04.tar # 注销原有分发版 wsl --unregister Ubuntu-20.04 # 导入到 E盘的新路径&#xff08;例如 E:\WSL\Ubuntu-20.04&#xff09; wsl --import Ubuntu-20.04 E:\WSL\Ubuntu-20.04 E:\wsl-ubuntu20.04.t…