入門篇-其之五-Java運算符(上)

来源:https://www.cnblogs.com/iCode504/archive/2023/10/09/17753411.html
-Advertisement-
Play Games

一、項目地址 https://github.com/LinFeng-BingYi/DailyAccountBook 二、新增 1. 在表格中設置選項列表,讓用戶更快地編輯動賬記錄 1.1 功能詳述 為表格中以下欄位設置選項列表: 1. 需求強度(由"基本需求"更名) 溫飽:基本維持生存且不鋪張浪費的 ...


一元運算符之正負號

Java支持多種一元運算符,一元運算符中的“一元”是指一個操作數。我們初中學過的正負號就屬於一元運算符,因為正負號後面只有一個數字。

正數使用+表示,其中+可以省略;負數使用-表示。如果變數的值是數值類型,也可以在變數前面加上正負號。

/**
 * 正負號的表示
 *
 * @author iCode504
 * @date 2023-10-06 19:49
 */
public class PlusAndMinusSign {
    public static void main(String[] args) {
        int intValue1 = 20;    // 正數,加號可忽略
        int intValue2 = -40;    // 負數
        System.out.println("intValue1 = " + intValue1);
        System.out.println("intValue2 = " + intValue2);

        // 變數的前面也可以加上正負號
        int intValue3 = 40;
        int intValue4 = -intValue3;
        System.out.println("intValue3 = " + intValue3);
        System.out.println("intValue4 = " + intValue4);

        // 加上符號的變數也可以參與運算,以下兩個變數相乘得到的結果是相同的
        int intValue5 = intValue3 * intValue4;  // 推薦寫法
        int intValue6 = intValue3 * -intValue3;     // 不推薦,可讀性變差
        System.out.println("intValue5 = " + intValue5);
        System.out.println("intValue6 = " + intValue6);

        // 負數前面加上負號為正數(負負得正)
        int intValue7 = -(-20);
        int intValue8 = -intValue4;     // intValue4本身的值就是負數
        System.out.println("intValue7 = " + intValue7);
        System.out.println("intValue8 = " + intValue8);
    }
}

運行結果:

image-20231006200450682

根據intValue7intValue8的輸出結果我們可以得知,負號可以改變數值的正負,正數加了負號變負數,負數加負號可以變正數(負負得正)。

編寫代碼不推薦int intValue6 = intValue3 * -intValue3;這種寫法,雖然能得到預期結果,但是右側計算的表達式可讀性變差,可能會造成誤解。

算數運算符

算術運算符的基本使用

在大多數編程語言中,算術運算符基本上由+、減-、乘*、除/、取餘%(也稱“取模”,也就是兩個數相除的餘數)組成,以上五個運算符在Java中也完全適用。

/**
 * 算術運算符--加減乘除、取餘
 *
 * @author iCode504
 * @date 2023-10-08 7:01
 */
public class MathOperators1 {
    public static void main(String[] args) {
        int intValue1 = 22;
        int intValue2 = 5;

        // 加減乘除運算
        int result1 = intValue1 + intValue2;
        System.out.println("intValue1 + intValue2 = " + result1);
        int result2 = intValue1 - intValue2;
        System.out.println("intValue1 - intValue2 = " + result2);
        int result3 = intValue1 * intValue2;
        System.out.println("intValue1 * intValue2 = " + result3);
        // 兩個整除相除,只保留整數部分,不會進行四捨五入操作
        int result4 = intValue1 / intValue2;
        System.out.println("intValue1 / intValue2 = " + result4);
        // 兩個整數取餘:22對5取餘得到的結果是2
        int result5 = intValue1 % intValue2;
        System.out.println("intValue1 % intValue2 = " + result5);
    }
}

運行結果:

image-20231008071109661

兩個整數運算得到的結果是整數,兩個浮點數運算得到的結果是浮點數,整數和浮點數進行運算時得到的結果是浮點數(因為整數類型會自動提升為浮點類型)。

/**
 * 整數和浮點數的運算、byte/short/char類型的運算
 *
 * @author iCode504
 * @date 2023-09-28 15:47:46
 */
public class MathOperators2 {
    public static void main(String[] args) {
        // 定義兩個變數intValue1,intValue2並賦值
        int intValue1 = 20;
        int intValue2 = 40;
        // 直接輸出intValue1和intValue2相加的和
        // 註意:下方輸出時,需要對要計算的表達式加上括弧,防止intValue1和intValue2轉換成字元串類型
        System.out.println("intValue1 + intValue2 = " + (intValue1 + intValue2));

        System.out.println("----------分割線----------");
        // byte、short、char進行運算時,會自動提升為int類型計算。
        // 如果轉換成想要的小範圍數據類型,需要進行強制類型轉換
        byte byteValue = 30;
        short shortValue = 50;
        char charValue = 30;
        // 錯誤寫法:
        // byte byteValue1 = byteValue + shortValue;
        // 正確寫法: 將計算的結果轉換成小範圍數據類型。註意:強制類型轉換時需要考慮到數據溢出的問題。
        byte byteValue1 = (byte) (byteValue + shortValue);
        short shortValue1 = (short) (shortValue + charValue);
        char charValue1 = (char) (byteValue + charValue);       // 得到的結果是Unicode字元表中對應的字元
        System.out.println("byteValue1 = " + byteValue1);
        System.out.println("shortValue1 = " + shortValue1);
        System.out.println("charValue1 = " + charValue1);
        System.out.println("----------分割線----------");
        // 浮點數參與計算:整數會自動提升為浮點類型
        double doubleValue1 = 0.1;
        double doubleValue2 = 0.2;
        int intValue3 = 30;
        System.out.println("doubleValue1 + intValue3 = " + (doubleValue1 + intValue3));
        System.out.println("doubleValue1 + doubleValue2 = " + (doubleValue1 + doubleValue2));
    }
}

運行結果:

image-20231008072150038

浮點數計算為什麼不准確?

從上述結果我們發現一個問題,double類型的值0.10.2相加得到的結果並不是0.3,而是0.30000000000000004,為什麼?

假設有兩個浮點數0.10.2,如果兩個值賦值給float類型和double類型,相加計算是不是0.3?

我們使用Java代碼來測試一下:

/**
 * 浮點數0.1和0.2分別使用float類型和double類型計算
 *
 * @author iCode504
 * @date 2023-10-06 17:00:21
 */
public class DecimalCalculation1 {
    public static void main(String[] args) {
        // float類型相加計算
        float floatValue1 = 0.1f;
        float floatValue2 = 0.2f;
        System.out.println("floatValue1 + floatValue2 = " + (floatValue1 + floatValue2));
        // double類型相加計算
        double doubleValue1 = 0.1;
        double doubleValue2 = 0.2;
        System.out.println("doubleValue1 + doubleValue2 = " + (doubleValue1 + doubleValue2));
        
        double doubleValue3 = 0.5;
        double doubleValue4 = 0.8;
        System.out.println("doubleValue3 + doubleValue4 = " + (doubleValue3 + doubleValue4));
    }
}

運行結果:

image-20231006193753117

此時發現一個問題:doubleValue1 + doubleValue2 = 0.30000000000000004並沒有得到我們預期的結果,為什麼?

事實上,0.1 + 0.2的結果在大多數編程語言中進行運算時也會得到上述結果,點我查看

眾所周知,電腦在底層計算使用的是二進位。無論是整數還是浮點數都會轉換成二進位數進行運算。以下是小數轉為二進位數運算的基本流程

flowchart LR 十進位數 --> 二進位數 --> 科學計數法形式表示二進位數 --> 指數補齊 --> 二進位數相加 --> 還原成十進位數

十進位小數轉為二進位小數

小數轉為二進位數的規則是:將小數乘以2,然後取整數部分作為二進位數的一部分,然後再將小數部分繼續乘以2,再取整數部分,以此類推,直到小數部分為0所達到的精度。

將0.2轉換成二進位:

\[0.2 \times 2 = 0.4 \to 取整數部分0 \]

\[0.4 \times 2 = 0.8 \to 取整數部分0 \]

\[0.8 \times 2 = 1.6 \to 取整數部分1 \]

\[0.6 \times 2 = 1.2\to取整數部分1 \]

\[0.2 \times 2 = 0.4\to整數部分為0 \]

此時我們發現,我們對得到的小數怎麼乘以2,小數位永遠都不是0。因此,使用計算器計算0.2得到的二進位數字為

\[0.00110011...(無限迴圈0011) \]

同理,0.1轉換成二進位數是:

\[0.000110011...(無限迴圈0011) \]

二進位小數轉為科學計數法表示

當然,電腦不能存儲無限迴圈小數。Java的double是雙精度浮點類型,64位,因此在存儲時使用64位存儲double浮點數。要想表示儘可能大的數據,就需要使用到科學計數法來表示數據。

十進位和二進位數都可以轉換成相應的科學計數法來表示。

十進位的科學計數法的表示方式是整數只留個位數,且個位數主要是1到9,通過乘以10的指數來表示。例如:89999用科學計數法表示為\(8.9999\times10^4\),0.08586用十進位科學計數法表示為\(8.586\times10^{-2}\)

二進位的科學計數法的表示方式和十進位的類似。它的個位數使用1來表示,通過乘以2的指數來表示

例如,0.1的二進位數轉換成科學計數法表示,小數點需要向右移動4位得到整數部分1;同理,0.2需要向右移動3位。因此0.1和0.2的二進位用科學計數法表示如下:

\[1.10011...\times2^{-4}(0011無限迴圈) \]

\[1.10011...\times2^{-3}(0011無限迴圈) \]

科學計數法的數據轉成二進位表示

Java的double類型是雙精度浮點數,IEEE 754標準對64位浮點數做出瞭如下的規定:

  • 最高1位是符號位,0表示正號,1表示負號。
  • 其後面的11位用來存儲科學計數法中指數的二進位。以上述二進位科學計數法為例,這11位數字存儲的就是-4的二進位。
  • 剩下的52位存儲二進位科學計數法中小數點的後52位。以上述二進位科學計數法為例,存儲的就是10011...之後的52位數字。
image-20231009084527660

既然記憶體已經給出了11位用於表示指數。那麼轉換成十進位數預設範圍就是\([0, 2^{11}]\),即\([0,2048]\)。但此時還有一個問題,以上述的二進位科學計數法為例,它的指數是-4,是負數,如何表示負數?需要在11位的頭部在單獨拿出一位來表示嗎?

並不是,IEEE 754標准將指數為0的基數定為1023(1是1024,相當於存儲\([-1023,1024]\)範圍的數),指數-4會轉換成1023 - 4 = 1019,再將1019轉換成二進位:1111111011,前面我們說過,指數為11位,需要在前面補零,得到的結果為:01111111011

剩下的52位也需要處理,但是二進位科學計數法的小數部分也是一個無限迴圈小數。此時就需要進行舍入計算,0舍1入(類似四捨五入),舍入計算會讓數據丟失精度

此時得到的0.1的二進位:

\[0\ 01111111011\ 1001100110011001100110011001100110011001100110011010 \]

0.2的二進位如下:

\[0\ 01111111100\ 1001100110011001100110011001100110011001100110011010 \]

此時需要對二進位科學計數法提取公因數,為了減少精度損失,遵循小指數轉換成大指數的原則。這裡較大的指數是-3,因此需要將0.1的二進位科學計數法再乘以2,得到結果如下:

\[0\ 01111111011\ (0.)100110011001100110011001100110011001100110011001101 \]

0.1原有的最後一位需要捨去,讓給小數點前的0。此時0.1和0.2的二進位的指數均為-3、

此時0.1+0.2的小數部分得到的結果是:

\[10.0110011001100110011001100110011001100110011001100111 \]

指數補齊

根據上述結果,我們會發現兩個問題:

  • 整數部分不符合科學計數法的規則。
  • 二進位數整體得到的結果超過52位。

首先需要將將結果轉換成二進位科學計數法,小數點向左移動一位(相當於乘以2):

\[1.00110011001100110011001100110011001100110011001100111 \]

指數部分也需要加1,因為指數由-3(1020)變為-2(1021)

\[01111111101 \]

根據0舍1入的原則,將超出52位的小數部分做舍入計算,得到的結果為:

\[0\ 01111111101\ (1.)0011001100110011001100110011001100110011001100110100 \]

還原成十進位數

將二進位科學計數法轉換成正常的二進位數,原有的指數是-2,還原時小數點需向左移動兩位:

\[0.010011001100110011001100110011001100110011001100110100 \]

再轉換為十進位為:

\[0.30000000000000004 \]

經過上述的複雜推導,我們可以總結出一個結論:使用基本數據類型的浮點數進行運算並不准確(尤其是在金融貨幣領域對小數點精度要求比較高的不能使用)。那麼,有什麼辦法可以解決浮點數計算不准確的問題?

方法一(現階段推薦):轉換成整數計算,得到結果再除以10的n次方

還是以0.1 + 0.2為例,我們可以轉換成整數計算,整數計算的結果再除以10,示例代碼如下:

/**
 * 浮點數計算: 計算0.1 + 0.2的精確結果
 *
 * @author ZhaoCong
 * @date 2023-10-09 18:13:35
 */
public class DecimalCalculation2 {
    public static void main(String[] args) {
        double doubleValue1 = 0.1;
        double doubleValue2 = 0.2;
        // 將doubleValue1和doubleValue2轉換成整數
        int tempValue1 = (int) (doubleValue1 * 10);
        int tempValue2 = (int) (doubleValue2 * 10);
        int tempResult = tempValue1 + tempValue2;
        double result = (double) tempResult / 10;
        System.out.println("result = " + result);
    }
}

運行結果:

image-20231009222458278

此時能得到精確的結果。

方法二:使用BigDecimal類(這個類後續會講到,小白可以直接跳過)精確運算

import java.math.BigDecimal;

/**
 * 使用BigDecimal類精確計算浮點數
 *
 * @author iCode504
 * @date 2023-10-09 22:26
 */
public class DecimalCalculation3 {
    public static void main(String[] args) {
        double doubleValue1 = 0.1;
        double doubleValue2 = 0.2;

        // 將double類型的值轉換成字元串
        String doubleValueString1 = String.valueOf(doubleValue1);
        String doubleValueString2 = String.valueOf(doubleValue2);

        // 使用BigDecimal類進行運算
        BigDecimal decimal1 = new BigDecimal(doubleValueString1);
        BigDecimal decimal2 = new BigDecimal(doubleValueString2);
        BigDecimal resultDecimal = decimal1.add(decimal2);
        double result = resultDecimal.doubleValue();
        System.out.println("result = " + result);
    }
}

運行結果:

image-20231009223129893

負數的除法和取餘規則

負數的除法規則:兩個負數相除得到的結果是正數,正數除以負數或者負數除以整數結果是負數

/**
 * 負數的除法運算
 *
 * @author iCode504
 * @date 2023-10-07 19:57
 */
public class DivideOperators {
    public static void main(String[] args) {
        int intValue1 = 20;
        int intValue2 = -10;
        int intValue3 = 5;
        int intValue4 = -5;

        // 情況一:被除數為正數,除數為負數,得到的結果是負數
        int result1 = intValue1 / intValue2;
        System.out.println("result1 = " + result1);

        // 情況二:被除數為負數,除數為正數,得到的結果是負數
        int result2 = intValue2 / intValue3;
        System.out.println("result2 = " + result2);

        // 情況三:被除數和除數都是負數,得到的結果是正數
        int result3  = intValue2 / intValue4;
        System.out.println("result3 = " + result3);
    }
}

運行結果:

image-20231007221818423

負數的取餘規則:被除數如果是正數,求餘的結果就是正數;反之,結果為負數

/**
 * 負數的取餘運算
 *
 * @author iCode504
 * @date 2023-10-07 22:12
 */
public class ModOperators {
    public static void main(String[] args) {
        int intValue1 = 20;
        int intValue2 = -13;
        int intValue3 = 7;
        int intValue4 = -3;

        // 情況一:被除數為正數,除數為負數,得到的結果是正數
        int result1 = intValue1 % intValue2;
        System.out.println("result1 = " + result1);

        // 情況二:被除數為負數,除數為正數,得到的結果是負數
        int result2 = intValue2 % intValue3;
        System.out.println("result2 = " + result2);

        // 情況三:被除數和除數都是負數,得到的結果是負數
        int result3 = intValue2 % intValue4;
        System.out.println("result3 = " + result3);
    }
}

運行結果:

image-20231007222009322

賦值運算符

賦值運算符=

我們知道,創建Java變數的一般語法是:數據類型 變數名 = 變數值。其中=是賦值運算符,它的作用是將右側的值賦值給左邊的變數

  • 變數值一般是:常量、已經賦值的變數名或者是可以計算出新數值的表達式。
  • 賦值運算符=左側的變數名唯一。

基本數據類型的變數可以直接賦值,因為基本數據類型保存的是實際值。

/**
 * 賦值運算符 = 的基本使用
 *
 * @author iCode504
 * @date 2023-10-06 6:40
 */
public class AssignmentOperator1 {
    public static void main(String[] args) {
        // 將20賦值給number1
        int number1 = 20;
        System.out.println("number1 = " + number1);
        // 將已經賦值的變數名number1賦值給number2
        int number2 = number1;
        System.out.println("number2 = " + number2);
        // 可以計算出新數值的表達式賦值給新變數
        int number3 = 30 + 40;
        System.out.println("number3 = " + number3);
        int number4 = number1 + number2;
        System.out.println("number4 = " + number4);
    }
}

運算結果:

image-20231006064803996

number1number2的輸出結果可知:變數number1存儲的值20賦值給了number2,此時number2的值也是20。

變數number3number4右側是可以計算的表達式,即30 + 40能夠直接計算出結果,前面已經賦值的number1 + number2也能計算出結果。

引用數據類型存儲的是一個地址值引用。例如:ObjectString是類,屬於引用數據類型。此時我們創建這兩個類型的對象並賦值給變數,然後直接輸出變數。

/**
 * 賦值運算符--引用數據類型變數賦值並輸出
 *
 * @author iCode504
 * @date 2023-10-06 23:50
 */
public class AssignmentOperator2 {
    public static void main(String[] args) {
        // 第一組:創建兩個Object對象分別賦值給object1和object2
        Object object1 = new Object();
        Object object2 = new Object();
        // 輸出兩個地址值
        System.out.println("object1 = " + object1);
        System.out.println("object2 = " + object2);

        System.out.println("--------------------");
        // 第二組:讓object1指向object2
        object2 = object1;
        System.out.println("object1 = " + object1);
        System.out.println("object2 = " + object2);

        System.out.println("--------------------");
        // 第三組:創建兩個String對象分別賦值給string1和string2
        String string1 = new String();
        String string2 = new String();
        System.out.println("string1 = " + string1);
        System.out.println("string2 = " + string2);
    }
}

運行結果:

image-20231007065141822

前兩組輸出結果的格式我們發現,它們是以java.lang.Object@和變數在物理記憶體中的地址(十六進位數)。

  • 其中java.lang.Object叫做全限定類名。全限定類名是指當前類所屬的包名(包名會在後續文章中講到)和類名組成。Object是類名,java.langObject類所在的包名。
  • @後面的就是變數在記憶體中的存儲地址。如果你使用上述命令將代碼輸出,那麼得到的地址值和上述的內容不同,因為變數的地址值是記憶體隨機分配的。

第一組的object1object2分別創建了Object對象,相當於在棧記憶體和堆記憶體中分別開闢了兩塊不同的空間,棧記憶體中存儲的變數地址和堆記憶體中開闢的記憶體地址一一對應,因此object1object2的地址值不同。第一組的object1object2在記憶體的表現形式如下:

image-20231007071809712

第二組,我們發現object1賦值給了object2,在棧記憶體中的表現形式是當前變數object2的地址值賦值給object1。原來object2在堆記憶體中創建的對象不再被引用,虛擬機後續會對此對象進行回收。

image-20231007215157582

我們發現第三組兩個String對象的輸出結果什麼都看不到,它們也是引用數據類型,難道不輸出地址值嗎?事實上,在源碼層面,String做了進一步處理。

我們使用new String()創建對象時,會調用String的構造器(構造器,也叫做構造方法,後續會講到),打開源碼觀察這個構造器:

image-20231007220335076

在調用空參構造器時就已經初始化一個空字元串值了,因此我們在輸出String對象時輸出的是空字元串,此時我們看不到任何內容就顯得比較合理了。

其他賦值運算符

假設有一個int類型變數intValue的值是20,此時我在此基礎上再加上20再賦值給intValue,得到的表達式如下:

int intValue = 20;
intValue = intValue + 20;		// 此時intValue的結果為40

Java給我們提供了+=運算符可以簡化當前的代碼intValue = intValue + 20;,使用+=可以簡化成如下形式:

int intValue = 20;
intValue += 20;		// 得到的結果也是40,相當於intValue = intValue + 20;

除了+=以外,-=*=/=%=的作用機制和+=完全相同。

賦值運算符 說明 使用
+= 加並賦值運算符:先相加,得到的結果再賦值 i = i + 20可以簡寫成i += 20
-= 減並賦值運算符:先相減,得到的結果再賦值 i = i - 20可以簡寫成i -= 20
*= 乘並賦值運算符:先相乘,得到的結果再賦值 i = i * 20可以簡寫成i *= 20
/= 除並賦值運算符:先相除,得到的結果再賦值 i = i / 20可以簡寫成i /= 20
%= 取餘並賦值運算符:先取餘,得到的結果再賦值 i = i % 20可以簡寫成i %= 20

以下是5個運算符在代碼中的應用:

/**
 * 其他賦值運算符+=、-=、*=、/=和%=的使用
 *
 * @author iCode504
 * @date 2023-10-07 20:14
 */
public class AssignmentOperator3 {
    public static void main(String[] args) {
        int intValue1 = 20;
        int intValue2 = 30;
        int intValue3 = 40;
        int intValue4 = 50;
        int intValue5 = 60;

        intValue1 += 30;
        intValue2 -= 40;
        intValue3 *= 50;
        intValue4 /= 10;
        intValue5 %= 7;
        System.out.println("intValue1 = " + intValue1);
        System.out.println("intValue2 = " + intValue2);
        System.out.println("intValue3 = " + intValue3);
        System.out.println("intValue4 = " + intValue4);
        System.out.println("intValue5 = " + intValue5);
    }
}

運行結果:

image-20231007203213625

byteshortchar三者使用上述賦值運算符時,不需要進行強制類型轉換:

/**
 * byte、short、char使用賦值運算符
 *
 * @author iCode504
 * @date 2023-10-07 20:34
 */
public class AssignmentOperator4 {
    public static void main(String[] args) {
        byte byteValue1 = 30;
        byte byteValue2 = 40;
        short shortValue = 10;
        char charValue = 'a';

        byteValue1 += byteValue2;
        System.out.println("byteValue1 = " + byteValue1);
        byteValue1 += 10;
        System.out.println("byteValue2 = " + byteValue2);

        charValue += byteValue1;
        shortValue += charValue;
        byteValue2 += shortValue;
        System.out.println("charValue = " + charValue);
        System.out.println("shortValue = " + shortValue);
        System.out.println("byteValue2 = " + byteValue2);
    }
}

運行結果:

image-20231007211517616

使用賦值運算符的優勢包括:

1. 簡潔性:使用+=可以在一行內同時完成加法計算和賦值操作,讓代碼更加簡潔。例如:i += 20就是i = i + 20的簡化寫法(其他賦值運算符亦同理)。

2. 性能優勢:在某些情況下,賦值運算符要比單獨的加法和賦值操作更快。

總的來說,使用賦值運算符可以增加代碼的簡潔性,提高性能,並使代碼更易於閱讀和理解。


參考資料:

0.1 + 0.2為什麼不等於0.3?

0.1+0.2為什麼不等於0.3,以及怎麼等於0.3

0.1 + 0.2 為什麼不等於 0.3???


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 一、環境介紹 本文環境,以及本文所採用資料庫為GreatSQL 8.0.32-24 $ cat /etc/system-release Red Hat Enterprise Linux Server release 7.9 (Maipo) $ uname -a Linux gip 3.10.0-11 ...
  • 目錄Vue模板應用{{}} 變數插值v-once 只會插值一次v-html 對HTML代碼插值v-bindHTML標簽屬性的插值在外部傳遞數值類型的數據到組件內部時, 必須使用v-bind指令的方式進行傳遞, 直接使用HTML屬性設置的方式傳遞會將傳遞的數據作為字元串傳遞v-on 監聽、綁定事件v- ...
  • 這裡給大家分享我在網上總結出來的一些知識,希望對大家有所幫助 前端換膚方案 - element+less無感換膚(無需頁面刷新) 前言 前不久在改造一個迭代了一年多的項目時,增加了一個換膚功能。通過自己的探索,總結出了一套比較合適的改造方案供大家參考,如有更好的方案歡迎評論區踴躍評論😄 先上效果: ...
  • three.js、webgl、3D煤礦隧道、三維井下人員定位、掘進面三維可視化、縱採面可視化、採集面可視化展示、設備檢測、數字孿生、物聯網3D、3d建築、3d庫房,bim管理系統 ...
  • 導讀 VTable: 不只是高性能的多維數據分析表格,更是行列間創作的方格藝術家! VTable是位元組跳動開源可視化解決方案 VisActor 的組件之一。 在現代應用程式中,表格組件是不可或缺的一部分,它們能夠快速展示大量數據,並提供良好的可視化效果和交互體驗。VTable是一款基於可視化渲染引擎 ...
  • 單例模式 一個類只有一個實例,並提供一個全局訪問此實例的點,哪怕多線程同時訪問。 單例模式主要解決了一個全局使用的類被頻繁的創建和消費的問題。 單例模式的案例場景 資料庫的連接池不會反覆創建 spring中一個單例模式bean的生成和使用 在我們平常的代碼中需要設置全局的一些屬性保存 七種單例模式的 ...
  • 本文介紹了一種基於線上流量實現對重構系統進行功能和性能驗證的實踐方案。針對線上流量如何攔截、如何錄製、如何存儲、如何回放以及如何發壓均作了詳細說明,為具有類似需求的讀者提供了一種可供參考的思路。 ...
  • 一起學習下架構的視角。 架構的視角 在筆者的知識體系中,實際上將架構分為業務架構、應用架構、雲基礎架構這幾大類,業務架構主要著眼於控制業務的複雜性,基礎架構著眼於解決分散式系統中存在的一系列問題。無論何種架構,都希望能實現系統的可變的同時保障業務的高可用。 很多時候架構的視角/分類沒有明顯的邊界,通 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...