成人无码视频,亚洲精品久久久久av无码,午夜精品久久久久久毛片,亚洲 中文字幕 日韩 无码

資訊專欄INFORMATION COLUMN

高精度數(shù)學(xué)運(yùn)算

liaosilzu2007 / 888人閱讀

摘要:使用,保證精度的同時(shí),能精準(zhǔn)的進(jìn)行四舍六入計(jì)算。類精確的數(shù)學(xué)運(yùn)算使用來(lái)實(shí)現(xiàn)精準(zhǔn)度因?yàn)榫鹊脑驑?gòu)造方法的結(jié)果有一定的不可預(yù)知性,例如因此建議使用。算法規(guī)則四舍六入五考慮,五后非零就進(jìn)一,五后皆零看奇偶,五前為偶應(yīng)舍去,五前為奇要進(jìn)一。

四舍六入計(jì)算
算法規(guī)則:
四舍六入五考慮,
五后非零就進(jìn)一,
五后皆零看奇偶,
五前為偶應(yīng)舍去,
五前為奇要進(jìn)一。

使用BigDecimal,保證精度的同時(shí),能精準(zhǔn)的進(jìn)行四舍六入計(jì)算。

優(yōu)化排列組合算法

關(guān)于排列組合公式,請(qǐng)百度。網(wǎng)上一大堆算法,都先計(jì)算階乘再相除。但實(shí)際上應(yīng)該先約分,一下子就節(jié)約了很多計(jì)算步驟。以排列公式來(lái)說(shuō)P(n,r)=n!/(n-r)!,實(shí)際計(jì)算中就是n 乘到 n-r就可以了。組合公式就是排列算法再除以r的階乘。

MathUtil類
import org.apache.commons.lang3.ArrayUtils;

import java.math.BigDecimal;
import java.math.RoundingMode;

/**
 * 精確的數(shù)學(xué)運(yùn)算
 * 

使用 {@link java.math.BigDecimal}來(lái)實(shí)現(xiàn)精準(zhǔn)度

* 因?yàn)榫鹊脑?strong>BigDecimal(double val)構(gòu)造方法的結(jié)果有一定的不可預(yù)知性,例如: *
 *   System.out.println(new BigDecimal(0.2)); //0.200000000000000011102230246251565404236316680908203125
 *   System.out.println(BigDecimal.valueOf(0.2f)); //0.20000000298023224
 *   System.out.println(BigDecimal.valueOf(0.2d)); //0.2
 *   System.out.println(BigDecimal.valueOf(0.2)); //0.2
 *   System.out.println(new BigDecimal("0.2")); //0.2
 * 
*

因此建議使用new BigDecimal(String)。 * @author BBF */ public final class MathUtil { /** * PI,比Math.PI多兩位 */ public static final double PI = 3.1415926535897932384626; /** * 默認(rèn)除法運(yùn)算精度 */ private static final int DEFAULT_SCALE = 10; private static final double NUM_ROUND = 0.5; /** * 運(yùn)算枚舉 */ private enum MathType { /** * 加法 */ ADD, /** * 減法 */ SUB, /** * 乘法 */ MULTI, /** * 除法 */ DIV } private MathUtil() { } /** * 轉(zhuǎn)換為{@link java.math.BigDecimal} *

為保證精度,先轉(zhuǎn)成{@link java.lang.String}然后再用構(gòu)造函數(shù)

* @param value 數(shù)值 * @return {@link java.math.BigDecimal} */ private static BigDecimal convertToBigDecimal(Number value) { return value == null ? BigDecimal.ZERO : new BigDecimal(value.toString()); } /** * 提供精確的加法、減法和乘法運(yùn)算 * @param type 運(yùn)算法則 * @param scale 精確到小數(shù)點(diǎn)后幾位,只在除法有效 * @param values 多個(gè)值 * @return 四則運(yùn)算結(jié)果 */ private static BigDecimal calculate(MathType type, int scale, Number[] values) { if (ArrayUtils.isEmpty(values)) { return BigDecimal.ZERO; } // 第一個(gè)數(shù)作為被加數(shù)、被減數(shù)或被乘數(shù) Number value = values[0]; BigDecimal result = convertToBigDecimal(value); for (int i = 1, l = values.length; i < l; i++) { value = values[i]; if (value != null) { switch (type) { case ADD: result = result.add(convertToBigDecimal(value)); break; case SUB: result = result.subtract(convertToBigDecimal(value)); break; case MULTI: result = result.multiply(convertToBigDecimal(value)); break; case DIV: result = result.divide(convertToBigDecimal(value), scale, RoundingMode.HALF_UP); break; default: break; } } } return result; } /** * 提供精確的冪運(yùn)算 * @param value 底數(shù) * @param n 指數(shù) * @return 冪的積 */ public static BigDecimal pow(Number value, int n) { return convertToBigDecimal(value).pow(n); } /** * 提供精確的加法運(yùn)算 * @param values 多個(gè)值的字符串 * @return 和 */ public static BigDecimal add(Number... values) { return calculate(MathType.ADD, DEFAULT_SCALE, values); } /** * 提供精確的減法運(yùn)算 * @param values 多個(gè)值的字符串 * @return 差 */ public static BigDecimal sub(Number... values) { return calculate(MathType.SUB, DEFAULT_SCALE, values); } /** * 提供精確的乘法運(yùn)算 * @param values 多個(gè)值的字符串 * @return 積 */ public static BigDecimal multi(Number... values) { return calculate(MathType.MULTI, DEFAULT_SCALE, values); } /** * 提供(相對(duì))精確的除法運(yùn)算 *

當(dāng)發(fā)生除不盡的情況時(shí),精確到小數(shù)點(diǎn)以后10位,以后的數(shù)字四舍五入

* @param values 多個(gè)值的字符串 * @return 商 */ public static BigDecimal div(Number... values) { return calculate(MathType.DIV, DEFAULT_SCALE, values); } /** * 提供(相對(duì))精確的除法運(yùn)算 *

當(dāng)發(fā)生除不盡的情況時(shí),由scale參數(shù)指定精度,以后的數(shù)字四舍五入

* @param scale 精確到小數(shù)點(diǎn)后幾位,只在除法有效 * @param values 多個(gè)值的字符串 * @return 商 */ public static BigDecimal divByScale(int scale, Number... values) { if (scale < 0) { throw new IllegalArgumentException("The scale must be a positive integer or zero"); } return calculate(MathType.DIV, scale, values); } /** * 四舍六入五成雙算法 *

四舍六入五成雙是一種比較精確比較科學(xué)的計(jì)數(shù)保留法,是一種數(shù)字修約規(guī)則。

*
   * 算法規(guī)則:
   * 四舍六入五考慮,
   * 五后非零就進(jìn)一,
   * 五后皆零看奇偶,
   * 五前為偶應(yīng)舍去,
   * 五前為奇要進(jìn)一。
   * 
* @param value 需要科學(xué)計(jì)算的數(shù)據(jù) * @param digit 保留的小數(shù)位 * @return 指定小數(shù)位數(shù)的數(shù)字 */ public static BigDecimal round(Number value, int digit) { // 小數(shù)進(jìn)位,然后取整計(jì)算,再退位得到結(jié)果 BigDecimal ratio = pow(10, digit); // 進(jìn)位后的數(shù)字 BigDecimal number = multi(value, ratio); // 獲取BigDecimal整數(shù)部分,直接舍棄小數(shù)部分 long integer = number.setScale(0, RoundingMode.DOWN).longValue(); // 獲取小數(shù)部分 double decimal = sub(number, integer).doubleValue(); if (decimal > NUM_ROUND) { // 四舍六入 integer = integer + 1; } if (decimal == NUM_ROUND && integer % 2 != 0) { // 五前為奇要進(jìn)一 integer = integer + 1; } return div(integer, ratio).setScale(digit, RoundingMode.HALF_UP); } /** * 計(jì)算階乘 *

n! = n * (n-1) * ... * end

* @param n 階乘起始 * @param end 階乘結(jié)束 * @return 結(jié)果 */ public static BigDecimal factorial(Number n, int end) { int st = n.intValue(); if (st < end) { return BigDecimal.ZERO; } if (st == end) { return BigDecimal.ONE; } return multi(n, factorial(sub(n, 1), end)); } /** * 計(jì)算階乘 *

n! = n * (n-1) * ... * 2 * 1

* @param n 階乘起始 * @return 結(jié)果 */ public static BigDecimal factorial(Number n) { return factorial(n, 1); } /** * 計(jì)算排列 *

P(n, r) = n!/(n-r)!

*

從n個(gè)不同的元素中,取r個(gè)不重復(fù)的元素,按次序排列

* @param n 總數(shù) * @param r 要取出數(shù)量 * @return 排列數(shù) */ public static long arrangement(int n, int r) { if (n < r) { return 0; } // 對(duì)公式約分,實(shí)際上是計(jì)算了n 到 n-r的階乘 return factorial(n, n - r).longValue(); } /** * 計(jì)算組合 *

C(n, r) = n!/((n-r)! * r!)

*

從n個(gè)不同的元素中,取r個(gè)不重復(fù)的元素,不考慮順序

* @param n 總數(shù) * @param r 要取出數(shù)量 * @return 組合數(shù) */ public static long combination(int n, int r) { if (n < r) { return 0; } // 組合就是排列的結(jié)果再除以r的階乘 return div(arrangement(n, r), factorial(r)).longValue(); } }
測(cè)試用例
import org.junit.Test;

import java.math.BigDecimal;

/**
 * MathUtil測(cè)試類
 * @author BBF
 */
public class MathUtilTest {

  @Test
  public void showBigDecimal() {
    System.out.println(new BigDecimal(0.2)); //0.200000000000000011102230246251565404236316680908203125
    System.out.println(BigDecimal.valueOf(0.2f)); //0.20000000298023224
    System.out.println(BigDecimal.valueOf(0.2d)); //0.2
    System.out.println(BigDecimal.valueOf(0.2)); //0.2
    System.out.println(new BigDecimal("0.2")); //0.2
  }

  @Test
  public void add() {
    BigDecimal bigDecimal = new BigDecimal("1.91");
    double ab = MathUtil.add(8, 0.1, 0.2f, 0.3d, bigDecimal).doubleValue();
    System.out.println("各種類型數(shù)值相加,預(yù)期:10.51  實(shí)際:" + ab);
  }

  @Test
  public void round() {
    System.out.println("四舍六入預(yù)期:4.24  實(shí)際:" + MathUtil.round(4.245, 2).toString());
    System.out.println("四舍六入預(yù)期:4.24  實(shí)際:" + MathUtil.round(4.2450, 2).toString());
    System.out.println("四舍六入預(yù)期:4.25  實(shí)際:" + MathUtil.round(4.2451, 2).toString());
    System.out.println("四舍六入預(yù)期:4.22  實(shí)際:" + MathUtil.round(4.2250, 2).toString());
    System.out.println("四舍六入預(yù)期:1.20  實(shí)際:" + MathUtil.round(1.2050, 2).toString());
    System.out.println("四舍六入預(yù)期:1.22  實(shí)際:" + MathUtil.round(1.2150, 2).toString());
    System.out.println("四舍六入預(yù)期:1.22  實(shí)際:" + MathUtil.round(1.2250, 2).toString());
    System.out.println("四舍六入預(yù)期:1.24  實(shí)際:" + MathUtil.round(1.2350, 2).toString());
    System.out.println("四舍六入預(yù)期:1.24  實(shí)際:" + MathUtil.round(1.2450, 2).toString());
    System.out.println("四舍六入預(yù)期:1.26  實(shí)際:" + MathUtil.round(1.2550, 2).toString());
    System.out.println("四舍六入預(yù)期:1.26  實(shí)際:" + MathUtil.round(1.2650, 2).toString());
    System.out.println("四舍六入預(yù)期:1.28  實(shí)際:" + MathUtil.round(1.2750, 2).toString());
    System.out.println("四舍六入預(yù)期:1.28  實(shí)際:" + MathUtil.round(1.2850, 2).toString());
    System.out.println("四舍六入預(yù)期:1.30  實(shí)際:" + MathUtil.round(1.2950, 2).toString());
  }

  @Test
  public void factorial() {
    System.out.println("階乘10!:預(yù)期:3628800  實(shí)際:" + MathUtil.factorial(10).toString());
  }

  @Test
  public void arrangement() {
    System.out.println("排列P(10,2),預(yù)期:90  實(shí)際:" + MathUtil.arrangement(10, 2));
  }

  @Test
  public void combination() {
    System.out.println("排列C(10,2),預(yù)期:45  實(shí)際:" + MathUtil.combination(10, 2));
  }
}

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/69515.html

相關(guān)文章

  • 系統(tǒng)的講解 - PHP 浮點(diǎn)數(shù)精度運(yùn)算

    摘要:浮點(diǎn)數(shù)類型包括單精度浮點(diǎn)數(shù)和雙精度浮點(diǎn)數(shù)。小結(jié)通過(guò)浮點(diǎn)數(shù)精度的問(wèn)題,了解到浮點(diǎn)數(shù)的小數(shù)用二進(jìn)制的表示。以后,在使用浮點(diǎn)數(shù)運(yùn)算的時(shí)候,一定要慎之又慎,細(xì)節(jié)決定成敗。 概述 記錄下,工作中遇到的坑 ... 關(guān)于 PHP 浮點(diǎn)數(shù)運(yùn)算,特別是金融行業(yè)、電子商務(wù)訂單管理、數(shù)據(jù)報(bào)表等相關(guān)業(yè)務(wù),利用浮點(diǎn)數(shù)進(jìn)行加減乘除時(shí),稍不留神運(yùn)算結(jié)果就會(huì)出現(xiàn)偏差,輕則損失幾十萬(wàn),重則會(huì)有信譽(yù)損失,甚至吃上官司,我...

    makeFoxPlay 評(píng)論0 收藏0
  • PHP處理數(shù)學(xué)精度

    摘要:后來(lái)我看了下,確實(shí)有這么一個(gè)擴(kuò)展庫(kù),處理任意精度數(shù)字,對(duì)于任意精度的數(shù)學(xué),提供了支持用字符串表示的任意大小和精度的數(shù)字的二進(jìn)制計(jì)算。 用編程語(yǔ)言做計(jì)算,很多時(shí)候浮點(diǎn)數(shù)精度都是困擾過(guò)我的問(wèn)題,即便是剛學(xué)PHP的新手也會(huì)在群里問(wèn)為什么我的計(jì)算結(jié)果明顯不對(duì),而我們總是老態(tài)龍鐘的丟出一句浮點(diǎn)數(shù)計(jì)算都存在精度問(wèn)題,并沒(méi)有提出過(guò)什么實(shí)質(zhì)性的改善。比如下面的計(jì)算 0.57*100: zhgxun-p...

    chaos_G 評(píng)論0 收藏0
  • PHP變量類型

    摘要:獲取變量的類型,使用函數(shù)。要檢驗(yàn)?zāi)硞€(gè)類型,可以使用函數(shù),如是在整形是在浮點(diǎn)型是在字符串如果需要將一個(gè)變量強(qiáng)制轉(zhuǎn)換為某類型,可以對(duì)其使用強(qiáng)制轉(zhuǎn)換或者函數(shù)。自起,此限制僅對(duì)包含變量時(shí)有效。 簡(jiǎn)介 PHP支持9種原始數(shù)據(jù)類型。 4種標(biāo)量類型: boolean布爾型 integer 整形 float 浮點(diǎn)型(也稱作double) string 字符串 3種復(fù)合類型: array...

    selfimpr 評(píng)論0 收藏0
  • Python基礎(chǔ)之(一)基本數(shù)據(jù)類型

    摘要:但是在轉(zhuǎn)化中,浮點(diǎn)數(shù)轉(zhuǎn)化為二進(jìn)制后,不會(huì)精確等于十進(jìn)制的。一般情況下,只要簡(jiǎn)單地將最終顯示的結(jié)果用四舍五入到所期望的十進(jìn)制位數(shù),就會(huì)得到期望的最終結(jié)果。四舍五入內(nèi)建函數(shù)。在中的第二個(gè)數(shù),表示要保留的小數(shù)位數(shù),返回值是一個(gè)四舍五入之后的數(shù)值。 數(shù)字 基本類型 首先,進(jìn)入Python交互模式中: //整數(shù) >>> 3 3 //長(zhǎng)整數(shù) >>> 3333333333333333333333...

    yagami 評(píng)論0 收藏0
  • 如何解決0.1 +0.2===0.30000000000000004類問(wèn)題

    摘要:方法使用定點(diǎn)表示法來(lái)格式化一個(gè)數(shù),會(huì)對(duì)結(jié)果進(jìn)行四舍五入。該數(shù)值在必要時(shí)進(jìn)行四舍五入,另外在必要時(shí)會(huì)用來(lái)填充小數(shù)部分,以便小數(shù)部分有指定的位數(shù)。如果數(shù)值大于,該方法會(huì)簡(jiǎn)單調(diào)用并返回一個(gè)指數(shù)記數(shù)法格式的字符串。在環(huán)境中,只能是之間,測(cè)試版本為。 showImg(https://segmentfault.com/img/remote/1460000011913134?w=768&h=521)...

    yuanzhanghu 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

閱讀需要支付1元查看
<