亚洲乱色熟女一区二区三区丝袜,天堂√中文最新版在线,亚洲精品乱码久久久久久蜜桃图片,香蕉久久久久久av成人,欧美丰满熟妇bbb久久久

LOGO OA教程 ERP教程 模切知識交流 PMS教程 CRM教程 開發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

C#.Net筑基-深入小數(shù)內(nèi)部存儲的秘密

freeflydom
2024年6月26日 11:32 本文熱度 2513

 

為什么0.1 + 0.2 不等于 0.3?為什么16777216f 等于 16777217f?為什么金錢計(jì)算都推薦用decimal?本文主要學(xué)習(xí)了解一下數(shù)字背后不為人知的存儲秘密。


01、數(shù)值類型

C#中的數(shù)字類型主要包含兩類,整數(shù)、小數(shù),C#中的小數(shù)都為浮點(diǎn)(?。?shù)。


void Main()

{

int a1 = 100;

int a2 = 0x0f; //15

var b2 = 0b11; //3

var x1 = 1;    //整數(shù)值默認(rèn)為int

var y1 = 1.1;  //小數(shù)值默認(rèn)為double

Add(1, 2.3); //3.3

Add(1, 3);   //4

}

private T Add<T>(T x, T y) where T : INumber<T>

{

return x + y * x;

}
  • var類型推斷時(shí),整數(shù)值默認(rèn)為int,小數(shù)值默認(rèn)為double。

  • .NET 7 新增的一個(gè)專門用來約束數(shù)字類型的接口 INumber<T> ,用來約束數(shù)字類型非常好用。

數(shù)值類型大多提供的成員:

🔸靜態(tài)字段說明
MaxValue最大值常量,Console.WriteLine(int.MaxValue); //2147483647
MinValue最小值常量
🔸靜態(tài)方法說明
Parse、TryParse轉(zhuǎn)換為數(shù)值類型,是比較常用的類型轉(zhuǎn)換函數(shù),參數(shù)NumberStyles可定義解析的數(shù)字格式
Max、Min比較值的大小,返回最大、小的值,int.Max(1,100) //100
Abs計(jì)算絕對值
IsInfinity是否有效值,無窮值
IsInteger是否整數(shù)
IsNaN是否為NaN
IsPositive是否零或正實(shí)數(shù)
IsNegative是否表示負(fù)實(shí)數(shù)

數(shù)值類型還有很多接口,如加、減、乘、除的操作符接口,作為泛型約束條件使用還是挺不錯(cuò)的。

🔸操作符接口說明
IAdditionOperators加法
ISubtractionOperators減法
IMultiplyOperators乘法
IDivisionOperators除法

public static T Power<T>(T v1, T v2) where T : INumber<T>,

IMultiplyOperators<T, T, T>, IAdditionOperators<T, T, T>

{

return v1 * v1 + v2 * v2;

}

02、小數(shù)、浮點(diǎn)數(shù)⁉

C#中的小數(shù)類型有float、double、decimal 都是浮點(diǎn)數(shù),浮點(diǎn) 就是“ 浮動小數(shù)點(diǎn)位置”,小數(shù)位數(shù)不固定,小數(shù)部分、整數(shù)部分是共享數(shù)據(jù)存儲空間的。相應(yīng)的,自然也有定點(diǎn)小數(shù),固定小數(shù)位數(shù),在很多數(shù)據(jù)庫中有定點(diǎn)小數(shù),C#中并沒有。

在編碼中我們常用的浮點(diǎn)小數(shù)是float、double,經(jīng)常會遇到精度問題,以及類似下面這些面試題。

  • ❓ 為什么0.1 + 0.2 不等于 0.3

  • ❓ 為什么浮點(diǎn)數(shù)無法準(zhǔn)確的表示 0.1?

  • ❓ 為什么16777216f 等于 16777217f?這里f表示為float。

  • ❓ 為什么32float可以最大表示3.402823E38,64double可以最大表示1.79*E308,那么點(diǎn)位數(shù)根本存不下???

  • ❓ 同樣是32位,float的數(shù)據(jù)范圍遠(yuǎn)超int,為什么?


Console.WriteLine(0.1 + 0.2 == 0.3);       //False

Console.WriteLine(16777216f == 16777217f); //True

Console.WriteLine(double.MaxValue); //1.7976931348623157E+308

Console.WriteLine(int.MaxValue);    //2147483647

Console.WriteLine(sizeof(double));  //8 //8字節(jié)(64位)

float、double為浮點(diǎn)數(shù),小數(shù)位數(shù)有限,比較容易損失精度。造成上面這些問題的根本原因是其存儲機(jī)制決定的,他們都遵循IEEE754格式規(guī)范,幾乎所有編程語言和處理器都支持該規(guī)范,因此大多數(shù)編程語言都有類似的問題。Decimal 為高精度浮點(diǎn)數(shù),存儲機(jī)制與float、double不同,她采用十進(jìn)制方式表示。

❗ 要搞懂float、double,就不得不了解IEEE754規(guī)范!

2.1、IEEE754:float、double存儲原理

IEEE 754 (維基百科)是一個(gè)關(guān)于浮點(diǎn)數(shù)算術(shù)的國際標(biāo)準(zhǔn),它定義了浮點(diǎn)數(shù)的表示格式、舍入規(guī)則、特殊值、浮點(diǎn)運(yùn)算等規(guī)范。IEEE 754 標(biāo)準(zhǔn)最早發(fā)布與1985年,其中包括了四種精度規(guī)范,其中最常用的就兩種:單精度(float,4字節(jié)32位)和雙精度(double,8字節(jié)64位)。大多數(shù)編程語言、硬件處理器都支持這兩種浮點(diǎn)數(shù)據(jù)類型,因此float、double的知識幾乎是所有語言通用的,可以深入了解一下,不虧的!

IEEE 754 浮點(diǎn)數(shù)不像十進(jìn)制字面量值那樣存儲,而是用下面的二進(jìn)制方式來表示并存儲的,其實(shí)就是二進(jìn)制的科學(xué)計(jì)數(shù)法。其二進(jìn)制表示包含三個(gè)部分:符號位S指數(shù)部分(階碼E,2為底的指數(shù))和尾數(shù)部分M

  • 🔸符號位(Sign):占用1位,這是浮點(diǎn)數(shù)的最高位,用于表示數(shù)字的正負(fù)。0表示正數(shù),1表示負(fù)數(shù)。

  • 🔸指數(shù)部分(Exponent,階碼):表示為2位底的指數(shù),這里使用了移碼,實(shí)際的指數(shù)e = E-127,這樣省去了指數(shù)的符號位,計(jì)算也更方便。

    • float 的指數(shù)部分8位,2^8=256 偏移量(移碼)為127,表示十進(jìn)制范圍為 [-127,128],其數(shù)據(jù)范圍就為 ±2^128 = ±3.4E38。指數(shù)全是1即指數(shù)值為255時(shí),表示為無效數(shù)字 ±infinity或NaN。

    • double 的指數(shù)部分11位,2^11=2048 偏移量(移碼)為1023,十進(jìn)制值范圍[-1023,1024],因此數(shù)據(jù)范圍 ±2^1024 = ±1.79E308。

  • 🔸尾數(shù)部分(Mantissa):這部分表示數(shù)字的精確值(有效數(shù)字),包括整數(shù)和小數(shù)部分。尾數(shù)長度決定了精度,因?yàn)橛行?shù)字長度是有限的,因此就必然存在精度丟失的問題。

    • float 的尾數(shù)部分23位,十進(jìn)制 2^23=8388608,最多6~7(不完整的第7位)位有效十進(jìn)制數(shù)字,只有前6位是完整的。

    • double 尾數(shù)長度52位,2^52 = 4503599627370496,因此最多有15~16 位有效十進(jìn)制數(shù)字。

IEEE754浮點(diǎn)數(shù)都會被轉(zhuǎn)換為上述二進(jìn)制形式:**符號*尾數(shù)*2^指數(shù)**,如 2 = 1.0 * 2^10.5 = 1.0 * 2^-1,5 = 1.25* 2^2。數(shù)據(jù)(整數(shù)、小數(shù)部分)先轉(zhuǎn)換為二進(jìn)制形式,然后左移或右移小數(shù)點(diǎn),轉(zhuǎn)換為1.M形式,始終都是 “1”開頭,因此就只存儲小數(shù)部分即可。

🚩浮點(diǎn)數(shù) =  


十進(jìn)制 2 就表示為 2 = 1.0* 2^1。下圖來自 在線IEEE754轉(zhuǎn)換器計(jì)算:IEEE-754 Floating Point Converter。

  • 階碼 E = 127+1 = 128(實(shí)際指數(shù)e=1) 。

  • 尾數(shù) 1.0,實(shí)際存儲的尾數(shù)就是0

十進(jìn)制 0.75 表示為0.75 = 1.5* 2^-1,指數(shù)為-1,尾數(shù)為1.5。

  • 階碼 E = 127+ (-1) = 126(實(shí)際指數(shù)e=-1) 。

  • 尾數(shù) 1.5,實(shí)際存儲的尾數(shù)就是0.5,二進(jìn)制值為0.1。為什么0.5 的二進(jìn)制為0.1呢,請看后續(xù)章節(jié)。

2.2、float、double對比

類型單精度 float雙精度 double
CTS類型System.SingleSystem.Double
長度4字節(jié)32位8字節(jié)64位
符號位S11
階碼(指數(shù)位T)8,[-127,128]11,[-1023,1024]
尾數(shù)M2352
階碼偏移量127,e= E -1271023,e= E -1023
精度(10進(jìn)制)**6~7 **,2^23=838860815~162^52 = 4503599627370496
范圍±3.402823E38 ,2^128=3.4E38±1.79*E308,2^1024=1.79E308
字面量表示(后綴)f/Fd/D

float只能用于 表示6~7個(gè)有效數(shù)字時(shí),才不會損失精度。


//7位有效數(shù)字

Console.WriteLine(4234567f);  //4234567

//第8位就不準(zhǔn)確了

Console.WriteLine(42345678f); //42345680

Console.WriteLine(42345671f); //42345670



//7位有效數(shù)字

Console.WriteLine(0.2345678f);  //0.2345678

//第8位就不準(zhǔn)確了

Console.WriteLine(2.12345678f); //2.1234567

Console.WriteLine(0.212345678f); //0.21234567

2.3、小數(shù)是怎么轉(zhuǎn)換為二進(jìn)制的?

對于整數(shù)轉(zhuǎn)換小數(shù)是非常容易理解的,計(jì)算機(jī)的二進(jìn)制是天然支持整數(shù)存儲為二進(jìn)制的。十進(jìn)制整數(shù)轉(zhuǎn)成二進(jìn)制通常采用 ”除 2 取余,逆序排列” 即可。


Console.WriteLine($"{1:B4}"); //0001

Console.WriteLine($"{2:B4}"); //0010

Console.WriteLine($"{3:B4}"); //0011

Console.WriteLine($"{4:B4}"); //0100

Console.WriteLine($"{5:B4}"); //0101

Console.WriteLine($"{8:B4}"); //1000

📢“B”格式只支持整數(shù),更多格式化參考《String字符串全面了解>字符串格式化大全

🚩乘2取整法

但小數(shù)則不同,采用的是 “乘2取整法”,小數(shù)部分循環(huán)迭代,直到小數(shù)部分=0為止。:如下0.875的十進(jìn)制浮點(diǎn)數(shù)轉(zhuǎn)換為二進(jìn)制格式為:0.111。

0.111,存儲為IEE754浮點(diǎn)數(shù),轉(zhuǎn)換為1.M*2^E結(jié)構(gòu),小數(shù)點(diǎn)右移一位,就是1.11*2^-1。

  • 指數(shù)E = -1 + 127 = 126 ,二進(jìn)制值為01111110

  • 尾數(shù)為 11 后面補(bǔ)0。

十進(jìn)制小數(shù)6.36 轉(zhuǎn)換為二進(jìn)制,整數(shù)部分+小數(shù)部分分別轉(zhuǎn)換后合體:

🚩無限循環(huán)的0.1!

二進(jìn)制無法準(zhǔn)確表示小數(shù)0.1,是因?yàn)?code style="margin: 0px 3px; padding: 0px 5px; box-sizing: border-box; font-family: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, "Liberation Mono", monospace, sans-serif; color: rgb(192, 52, 29); background-color: rgb(251, 229, 225); border-radius: 3px; line-height: 1.8; display: inline-block; overflow-x: auto; vertical-align: middle; border: none !important; text-indent: initial;">0.1 轉(zhuǎn)換為二進(jìn)制后是無限循環(huán)的,0.0 0011 0011 0011...,“0011”無限循環(huán)。就像十進(jìn)制小數(shù)1/3 = 0.333 一樣。

轉(zhuǎn)換為1.M*2^E結(jié)構(gòu),小數(shù)點(diǎn)右移4位,尾數(shù)就是1.1001 1001,指數(shù) E = -4 +127 = 123

2.4、浮點(diǎn)數(shù)的精度是怎么回事?

計(jì)算機(jī)存儲整數(shù)很簡單,每個(gè)數(shù)字是確定的。但小數(shù)則不同,0到1之間的小數(shù)都無限種可能,計(jì)算機(jī)有限的空間無法存儲無限的小數(shù)。因此計(jì)算機(jī)將小數(shù)也當(dāng)成“離散”的值,就像整數(shù)那樣,整數(shù)之間間隔始終為1。給小數(shù)一個(gè)間隔刻度,如下圖,用鐘表來舉例,小數(shù)刻度(步進(jìn))為0.234(十進(jìn)制)。

這樣做的好處可以兼顧“所有”小數(shù),小數(shù)的精度就取決于鐘表的“刻度”,刻度越小,精度越高,當(dāng)然存儲時(shí)所需要的空間也就越大。

因此,這個(gè)精度本質(zhì)上是由表盤間隔刻度(Gap)決定的,即使0.0012的間隔刻度,精度達(dá)到了4位十進(jìn)制數(shù),也只能保障前2~3位小數(shù)是可靠的。0.001X、0.002X、0.003X,他始終無法表示0.0013、0.0025。

可通過提高刻度(Gap)來提高精度,但存儲長度是有限的,因此不管是那種浮點(diǎn)數(shù)都是有精度限制的。精度越高的數(shù)據(jù)類型,也需要更多的長度來存儲數(shù)據(jù)。

32位float 用了23位來存儲有效數(shù)字,十進(jìn)制也就6~7位(2^23=8388608)。在IEEE754規(guī)范中,小數(shù)的“刻度”并不是均勻分布的,而是越來越大,數(shù)值越大則精度越低。如下面的表盤和刻度尺的示意圖,其精度(Gap)的分布是不均勻的,0附近數(shù)字的精度最高,然后精度就越來越低了,低到超過1。

看看 float 的間隔刻度(Gap)如下圖,來自官方IEEE_754文檔

  • 當(dāng)數(shù)值大于8388608時(shí),刻度(Gap)為1,就不能包含小數(shù)了。

  • 當(dāng)數(shù)字大于16777216(1600+萬)時(shí)間隔刻度為2,連整數(shù)精度都不能保證了😂。


//float大于8388608后的間隔為1

Console.WriteLine(8388608.1f == 8388608.4f); //True

//大于16777216后的間隔為2

Console.WriteLine(16777216f == 16777217f); //True

Console.WriteLine(16777218f == 16777219f); //False

Console.WriteLine(16777219f == 16777220f); //True

下圖是double的刻度表:小于8的數(shù)字都能有16位精度。

😂 怎么感覺float很雞肋呢?限制太多了!所以編程中浮點(diǎn)數(shù)多大都用的 double 居多,float比較少。


03、更精確的 Decimal

System.Decimal 是16字節(jié)(128位)的高精度十進(jìn)制浮點(diǎn)數(shù),不同于float、double 的二進(jìn)制存儲機(jī)制,Decimal 采用10進(jìn)制存儲,表示-7.9E28 到 +7.9E28之間的十進(jìn)制數(shù)。Decimal 最大限度地減少了因舍入而導(dǎo)致的錯(cuò)誤,比較適用于對精度要求高場景,如財(cái)務(wù)計(jì)算。

📢 Decimal并不屬于IEEE754規(guī)范,也不是處理器支持的類型,計(jì)算性能要差一點(diǎn)點(diǎn)(約 double 的 10%)。


Console.WriteLine(1f / 3f * 3f); //1

Console.WriteLine(0.1 + 0.2 == 0.3); //False

//decimal更高精度

Console.WriteLine(1m / 3m * 3m); //0.9999999999999999999999999999

Console.WriteLine(0.1m + 0.2m == 0.3m); //True

Decimal可以準(zhǔn)確的表示0.1,Decimal 128位的存儲結(jié)構(gòu)如下圖(圖來源):

  • 96位存儲一個(gè)大整數(shù),就是有效數(shù)字,Math.Pow(2,96) = 7.9E28,最多28位有效數(shù)字,因此小數(shù)最多也就是28位(全是小數(shù)時(shí))。

  • 剩下的32位中,有一個(gè)符號位,0 表示正數(shù),1 表示負(fù)數(shù)。其中有5位(下圖中的第111位)表示10的指數(shù)部分(0到28的整數(shù)),可以理解為小數(shù)點(diǎn)的位置,其他位數(shù)沒有使用默認(rèn)為0(有點(diǎn)浪費(fèi)呢?)。

Decimal 表示小數(shù)其實(shí)是“障眼法”,內(nèi)部有三個(gè)int (High、Mid、Low)來表示96位有效數(shù)字,還有一個(gè)int表示指數(shù)??梢酝ㄟ^ decimal.GetBits()方法獲取他們的值。下圖來自 Decimal 源碼 Decimal.cs

3.1、為什么Decimal沒有0.1問題?

在Decimal中就沒有 0.1+0.2 不等于0.3 的問題,因?yàn)樗軠?zhǔn)確表示0.1。

其根本原因就是 Decimal 不會把小數(shù)轉(zhuǎn)換為二進(jìn)制,而是就用十進(jìn)制。把小數(shù)都轉(zhuǎn)為整數(shù)存儲,如 0.1在Decimal 中會被表示為 1* 10^-1,尾數(shù)為1,指數(shù)為-1指數(shù)就是小數(shù)點(diǎn)位置。

📢 Decimal值 = 

 

var arr = decimal.GetBits(0.1M);

Console.WriteLine($"尾數(shù):{arr[2]}{arr[1]}{arr[0]}");

Console.WriteLine($"指數(shù):"+$"{arr[3]:B32}".Substring(0,16));

//尾數(shù):001

//指數(shù):0000000000000001

100.1024 存儲為1001024* 10^-4。

  • 尾數(shù)為1001024,全都轉(zhuǎn)換為整數(shù)了。不用擔(dān)心超出整數(shù)int范圍,96位有三個(gè)整數(shù)并行存儲呢!

  • 指數(shù)為4,小數(shù)點(diǎn)位置在第四格。


var arr = decimal.GetBits(100.1024M);

Console.WriteLine($"尾數(shù):{arr[2]}{arr[1]}{arr[0]}");

Console.WriteLine($"指數(shù):"+$"{arr[3]:B32}".Substring(0,16));

//尾數(shù):001001024

//指數(shù):0000000000000100

如果是負(fù)數(shù)-100.1024,則只有符號位為1,其他一樣


var arr = decimal.GetBits(-100.1024M);

Console.WriteLine($"尾數(shù):{arr[2]}{arr[1]}{arr[0]}");

Console.WriteLine($"指數(shù):"+$"{arr[3]:B32}".Substring(0,16));

//尾數(shù):001001024

//指數(shù):1000000000000100

📢 所以 Decimal 值只要沒有超過28~29位有效數(shù)字,就沒有精度損失!是不是Very Nice!flaot、double 損失精度的根本原因是其存儲機(jī)制,必須把小數(shù)轉(zhuǎn)換為二進(jìn)制值,再加上有限的精度位數(shù)。

3.2、Decimal、Double、Float對比

類型單精度 float雙精度 doubleDecimal 高精度浮點(diǎn)數(shù)
類型System.SingleSystem.DoubleSystem.Decimal
規(guī)范IEEE754IEEE754無,.Net自定義類型
是否基元類型
長度32位(4字節(jié))64位(8字節(jié))128位(16字節(jié))
內(nèi)部表示二進(jìn)制,基數(shù)為2二進(jìn)制,基數(shù)為2十進(jìn)制,基數(shù)為10
字面量(后綴)f/F后綴d/D后綴m/M
最大精度6~715~1628~29位
范圍±3.4E38 ,2^23=3.4E38范圍很大,±1.7*E308-2^(96) 到 2^(96),±7.9E28
特殊值+0、-0、+∞、-∞、NaN+0、-0、+∞、-∞、NaN
速度處理器原生支持,速度很快處理器原生支持,速度很快非原生支持,約double10%

Decimal 雖然精度高,但長度也大,計(jì)算速度較慢,所以還是根據(jù)實(shí)際場景選擇。財(cái)務(wù)計(jì)算一般都用 Decimal 是因?yàn)樗麑纫筝^高,錢不能算錯(cuò),傳說算錯(cuò)了要從程序員工資里扣😂😂。


04、一些編程實(shí)踐

  • 對于精度要求高的場景不適合用浮點(diǎn)數(shù)(double、float),推薦decimal,特別是價(jià)格、財(cái)務(wù)計(jì)算。

  • 浮點(diǎn)數(shù)不適合直接相等比較,直接相等大多會出Bug。

  • 在存儲比較大的數(shù)字時(shí),需注意float、double 對于整數(shù)也有精度問題。

4.1、浮點(diǎn)數(shù)的相等比較

  • 使用相同的精度進(jìn)行比較,Math.Round()獲取相同的精度值。

  • 比較相似性,根據(jù)實(shí)際場景設(shè)定一個(gè)誤差值,如1e-8,只要差值在這個(gè)誤差范圍內(nèi),都認(rèn)為相等。


var f1 = 0.1 + 0.2;

var f2 = 0.3;



Console.WriteLine(f1 == f2); //False

//相同精度

Console.WriteLine(Math.Round(f1,6) == Math.Round(f2,6)); //True

//誤差范圍

Console.WriteLine(Math.Abs(f1-f2)<1e-8); //True

4.2、取整與四舍五入

取整方式說明/示例
整數(shù)相除 10/4=2拋棄余數(shù),只留整數(shù)部分
強(qiáng)制轉(zhuǎn)換(int)2.9=2直接截?cái)?,只留整?shù)部分,需要注意‼️
Convert轉(zhuǎn)換,四舍五入取整Convert.ToInt32(2.7) = 3; Convert.ToInt32(2.2) = 2;
格式化截?cái)?,四射五?/td>字符串格式化時(shí)的截?cái)?,都是四舍五入?nbsp;$"{2.7:F0}" = "3"
Math.Ceiling(),向上取整Math.Ceiling(2.3) = 3,⁉️注意負(fù)數(shù)Math.Ceiling(-2.3) = -2
Math.Floor(),向下取整Math.Floor(2.3) = 2,⁉️注意負(fù)數(shù)Math.Floor(-2.3) = -3
Math.Truncate(),截?cái)嗳≌?/td>Math.Truncate(2.7) = 2,只保留整數(shù)部分,同強(qiáng)制轉(zhuǎn)換
Math.Round(),四舍五入可指定四舍五入精度,Math.Round(2.77,1) = 2.8


轉(zhuǎn)自https://www.cnblogs.com/anding/p/18221160 作者安木夕


該文章在 2024/6/26 11:37:48 編輯過
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場作業(yè)而開發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉儲管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購管理,倉儲管理,倉庫管理,保質(zhì)期管理,貨位管理,庫位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved