<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                ## 背景 我們打開MySQL客戶端,執行下面的SQL語句: ~~~ drop table if exists t; create table t(id double)engine=innodb; insert into t values(1e-15),(1e-16); select * from t; ~~~ `select * from t`出來的內容如下,我們看到浮點數1e-15用正常的數值來表示,1e-16用科學技術法來表示。 ~~~ +-------------------+ | id | +-------------------+ | 0.000000000000001 | | 1e-16 | +-------------------+ ~~~ 我們知道在計算機中浮點數用來近似表示某個實數。浮點數有2種顯示風格,一種是正常的表示(0.18, 2.345等),一種是科學技術法的表示(1.23e+12,2.45e-16等)。那么MySQL的浮點型在什么情況下表示成正常的實數(如0.18,2.345),什么情況下表示成科學計數法(如1.23e+12,2.45e-16)呢?下面我們進行更精確的實驗以及從源碼角度來解釋MySQL對于浮點數的顯示問題。 ## 實驗 我們用下面的SQL語句直接顯示多個浮點數: ~~~ select (1e+14),(1e+15),(2.3e+14),(2.3e+15),(1e-15),(1e-16),(3.4e-15),(3.4e-16); ~~~ select出來的內容是: ~~~ +-----------------+-------+-----------------+---------+-------------------+-------+--------------------+---------+ | 1e+14 | 1e+15 | 2.3e+14 | 2.3e+15 | 1e-15 | 1e-16 | 3.4e-15 | 3.4e-16 | +-----------------+-------+-----------------+---------+-------------------+-------+--------------------+---------+ | 100000000000000 | 1e15 | 230000000000000 | 2.3e15 | 0.000000000000001 | 1e-16 | 0.0000000000000034 | 3.4e-16 | +-----------------+-------+-----------------+---------+-------------------+-------+--------------------+---------+ ~~~ 通過以上的例子再結合更多的實驗我們可以看出這么一個規律: 1. 在數值大于0時,科學計數法表示的指數小于或等于14時,select出來的是正常非科學計數法的數值; 2. 在數值大于0時,科學計數法表示的指數大于14時,select出來的是科學計數法的數值; 3. 當數值小于0時,科學計數法表示的指數大于或等于-15時,select出來的是正常非科學計數法的數值; 4. 當數值小于0時,科學計數法表示的指數小于-15時,select出來的是科學計數法的數值。 另外由于上面的select并沒有來自某個具體表,所以浮點數展示的規則是和存儲引擎沒有關系的,MySQL對于浮點數展示包裝的邏輯是在server層完成的。 我們去代碼里驗證一下這個規律是否正確。 ## 驗證 我們可以用gdb跟到代碼里面尋找這塊邏輯,但是MySQL單單server層的代碼也有好幾萬行,盲目的跟代碼并不能很快的找到我們要找的位置。所以,跟代碼前我們很有必要先分析一下這塊邏輯會出現在什么位置。 我們知道MySQL對select的處理的大體過程是,客戶端向服務端發送select,服務端解析select并把結果返回到客戶端,那么這塊邏輯就很有可能出現在服務端把結果送到客戶端這個過程中。 最后通過跟蹤代碼我們發現了在MySQL將結果返回客戶端的過程中,在下面這個位置的`buffer->set_real`對要顯示的內容進行了包裝,并把包裝的結果放到buffer這個變量里。 ~~~ sql/protocol.cc: bool Protocol_text::store(double from, uint32 decimals, String *buffer) { #ifndef DBUG_OFF DBUG_ASSERT(field_types == 0 || field_types[field_pos] == MYSQL_TYPE_DOUBLE); field_pos++; #endif buffer->set_real(from, decimals, thd->charset()); return net_store_data((uchar*) buffer->ptr(), buffer->length()); } ~~~ 在對set_real往更深的調用層次跟蹤,我們找到了對浮點數的展示進行包裝的位置: ~~~ strings/dtoa.c: ... size_t my_gcvt(double x, my_gcvt_arg_type type, int width, char *to, my_bool *error) ... ~~~ 通過分析`my_gcvt`這個函數,我們可以得出MySQL對于浮點數展示的規則。 首先我們必須知道以下這個事實(下面’f’format表示正常格式,’e’format表示科學計數法的格式): MySQL對select出來的每一列占用的寬度是有要求的,如果浮點數在’f’format下的有效數字太多,就有可能超過最大寬度,這時若還想要用’f’format,就不得不丟失一些有效數字了。如果同樣數值的’e’format不會丟失有效數字,MySQL就會把該浮點數從’f’format轉為’e’format。 下面的這個if語句確定了用’f’format表示浮點數的條件。 ~~~ strings/dtoa.c -> function my_gcvt if ((have_space || /* Not enough space, let's see if the 'f' format provides the most number of significant digits. */ ((decpt <= width && (decpt >= -1 || (decpt == -2 && (len > 1 || !force_e_format)))) && !force_e_format)) && /* Use the 'e' format in some cases even if we have enough space for the 'f' one. See comment for MAX_DECPT_FOR_F_FORMAT. */ (!have_space || (decpt >= -MAX_DECPT_FOR_F_FORMAT + 1 && (decpt <= MAX_DECPT_FOR_F_FORMAT || len > decpt)))) ~~~ 代碼有點亂,但是通過看注釋以及上下文,我們可以分析出用’f’format表示浮點數必須同時滿足2個條件: 1\. 用’f’format表示浮點數不會因為寬度限制造成精度丟失; 2\. 浮點數用若用’e’format表示時的指數在一個臨界值范圍(-15,14)內,那么就用’f’format表示。 在前面的實驗中,我們給出的幾個浮點數若用’f’format并不會超過列的最大寬度,即滿足條件1。那么這幾個浮點數用’f’format還是’e’format表示就由條件2決定了,條件2和我們在實驗中看到的規律相符。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看