【面試場景題】隨機立減金額計算

文章目錄

  • 背景
  • 設計思路
  • 方案
  • 結論
  • 高斯分布(正態分布)

背景

某電商公司跟某銀行有合作,推進銀行信用卡辦卡&流水,使用此銀行信用卡用戶,支付可以隨機立減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
英文地址,請注明出處:http://en.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…