2014-09-30 19 views
10

Firebird, yuvarlama yerine bölme yaparken ondalık basamakları keser. Ayrıca, döndürülen değerdeki ondalık sayıların sayısını pay ve paydadaki ondalık basamak sayısına dayandırır.Firebird neden bölündüğünde ondalık basamakları keser?

Firebird neden yuvarlama yerine kırpılıyor? Ve neden döndürülen değeri sorgudaki ondalık basamakların sayısına dayandırıyor?

Firebird 2.5:

select 187/60.00 from rdb$database; --result: 3.11 
select 187.000/60 from rdb$database; --result: 3.116 
select 187.000/60.00 from rdb$database --result: 3.11666 

2012, SQL Server:

select 187/60.00; --result: 3.116666 

Oracle 11gR2:

select 187/60.00 from dual; --result: 3.116666666667 

MySQL 5.5.32:

select 187/60.00 from dual; --result: 3.1167 

PostgreSQL 9.3.1:

select 187/60.00; --result: 3.116666666667 

SQLite: ondalık basamağa sahip Firebird değişmezleri olarak

select 187/60.00; --result: 3.1166666666666667 

cevap

11

, tip NUMERIC olmayan DOUBLE PRECISION (veya başka bir kayan nokta tipi) bulunmaktadır. Bu, tam sayısal hesaplama kurallarını uygulayacağı anlamına gelir.

select 187/60.00 from rdb$database ile, bu, 187'nin INTEGER ve 60.00'ın NUMERIC(18,2) olduğunu gösterir.

tam bir sayısal hesaplama kuralları "Exact Numerics - Functional Specification" bulunabilir: iki işlenen OP1 ve OP2 ölçekli S1 ve S2 tam bir sayısal sırasıyla ise

, daha sonra OP1 + OP2 ve OP1-OP2 ile tam bir sayısal olarak Hassasiyet 18 ve S1 ve S2'nin büyüklüğünü ölçeklendirirken, OP1 * OP2 ve OP1/OP2 hassas 18 ve ölçek S1 + S2 ile tam sayısaldur. (Bu işlemin bölümlendirmesi hariç ölçekler SQL standardıyla belirlenir. Standart, tüm bu operasyonların doğruluğunu ve uygulamaların tanımlı olduğu ölçeklemenin ölçeğini yapar: hassasiyeti 18 olarak tanımlar ve bölünme ölçeğini S1 + olarak belirleriz. S2, çarpma durumunda standardının gereğidir aynı.) işlenen biri ayrılmaz bir tip, o yüzden bu durumda ölçek 0. sahip bir sayısal olarak kabul edilir

Eğer NUMERIC(18,0)/NUMERIC(18,2) var ve yukarıdaki kurallara dayanarak, sonuç NUMERIC(18, 0+2) = NUMERIC(18,2).

Sayının kırpılmış gibi göründüğü gerçeği, tam sayısal hesaplamanın uygulanmasının bir sonucudur: hesaplama, son basamak hesaplandıktan sonra durur. aşağıdaki olduğu gibi 2011 Foundation şartname Firebird bir tam sayı doğrudur olmaya 60.00 gördüğü gerçeği: SQL baktığımızda

60.00/187 \ 3.11 
     180 
     --- 
      70 
      60 
      -- 
      100 
      60 
      -- (stop) 
      40 

: Bir kalanı olduğu gerçeği hesaplamanın sonucu ile bir ilgisi yoktur 5. bölümdeki hazırlıklar için üretim kuralları.literal :

<literal> ::= 
    <signed numeric literal> 
    | <general literal> 

<unsigned literal> ::= 
    <unsigned numeric literal> 
    | <general literal> 

<signed numeric literal> ::= 
    [ <sign> ] <unsigned numeric literal> 

<unsigned numeric literal> ::= 
    <exact numeric literal> 
    | <approximate numeric literal> 

<exact numeric literal> ::= 
    <unsigned integer> [ <period> [ <unsigned integer> ] ] 
    | <period> <unsigned integer> 

<sign> ::= 
    <plus sign> 
    | <minus sign> 

<approximate numeric literal> ::= 
    <mantissa> E <exponent> 

<mantissa> ::= 
    <exact numeric literal> 

<exponent> ::= 
    <signed integer> 

<signed integer> ::= 
    [ <sign> ] <unsigned integer> 

<unsigned integer> ::= 
    <digit>... 

Ve sözdizimi kuralları:

21) bir <period> olmadan bir <exact numeric literal> bir son <digit> aşağıdaki <period> ima etti.
22) <exact numeric literal> ENL'nin bildirilen türü, ölçeği, <period>'un sağında bulunan <digit> s sayısı olan, uygulama tarafından tanımlanan tam sayısal bir türdür. ENL'nin değerini tam olarak temsil edebilecek kesin bir sayısal tip olmalıdır.

1) bir diyadik aritmetik operatörün her işlenen beyan türü tam sayı, sonucun daha sonra açıklanacaktır türü ise:

Bölüm 6.27 < sayısal değer ifade > aşağıdaki sözdizimi kuralları kapsar aşağıdaki gibi belirlenen hassasiyet ve ölçek ile uygulama tanımlı tam sayısal bir türdür: a) S1 ve S2 sırasıyla birinci ve ikinci işlenenlerin ölçeği olsun.
b) Toplama ve çıkarma işleminin kesinliği uygulama tanımlıdır ve ölçek S1 ve S2'nin maksimum değeridir.
c) Çarpma sonucunun kesinliği uygulama tanımlıdır ve ölçek S1 + S2'dir.
d) Bölünme sonucunun kesinliği ve ölçeği uygulama tanımlıdır. Başka bir deyişle


Firebird davranışı SQL standardına uygundur. Çalıştığınız veritabanının çoğuna (SQL Server istisnai olarak) bakarak, ya bölünme için ölçek için nispeten büyük bir değer kullanın ya da yaklaşık sayısal (çift çifte hassasiyet) davranışını kullanın.

Bir geçici çözüm, yaklaşık sayısal bir literal kullanmak olacaktır. Üs sıfır veya E0 kullanımı, on ek güç olmaksızın bu sayıyı iki katına çıkarır. Örneğin:

select 187E0/60.00 from rdb$database; -- result: 3.116666666666667 
-- or 
select 187/60.00E0 from rdb$database; -- result: 3.116666666666667 
İlgili konular