Discussion:
mysql round()
Horváth Ágoston János
2004-11-12 14:10:57 UTC
Permalink
Üdv!

Elég összetett problémába sikerült belefutnom. A következő a helyzet:
van egy mysql 4.0 (de a 4.1 is ugyanezt produkálja), ahol ha kiadom
mysql konzolból a következő parancsokat, ezt kapom:

create table test (valami decimal(5,2));
insert into test values (5.55);
insert into test values (5.555);
insert into test values (5.556);
select * from test;
+--------+
| valami |
+--------+
| 5.55 |
| 5.55 |
| 5.56 |
+--------+


Látható, hogy a kerekítés nem egészen működik, de legalábbis elég
furán. Ezzel eddig semmi gond sincs, a google egy egész halom oldalt
dob ki, ahol hasonló gondokat reportoltak. A gond ott kezdődik, hogy a
mysql team válasza az, hogy ők simán meghívják a libc round()
függvényét, így implementáció-függő, hogy mi fog történni.

Ez eddig OK, nyilván ez a leggyorsabb, de attól még hibás. Ráadásul,
én a mysql.com -ról letöltött, általuk statikusra fordított és
tesztelt bináris pakkot használom, szóval még csak azt se lehet
mondani, hogy nálam lenne a hiba.

Tehát: tud-e valaki olyan lehetőséget, ami a libc round() működését
befolyásolná, vagy bármi más módon lehetővé tenné, hogy kicsikarjak
normális kerekítést a mysql-ből? Bármilyen megoldás érdekel, kivéve a
truncate, floor és ceiling, valamint egyéb SQL-függvények, mert
iszonyat kényelmetlen -és a projektünk jelenlegi állapotában
kivitelezhetetlen- minden queryt felülvizsgálni.

Kösz,
Horváth Ágoston
KORN Andras
2004-11-12 14:54:04 UTC
Permalink
Post by Horváth Ágoston János
Tehát: tud-e valaki olyan lehetőséget, ami a libc round() működését
befolyásolná, vagy bármi más módon lehetővé tenné, hogy kicsikarjak
normális kerekítést a mysql-ből? Bármilyen megoldás érdekel, kivéve a
LD_PRELOAD-olhatnal egy olyan libraryt, amiben mast csinal a round().
Mondjuk statikusan forditott binarison ez valoszinuleg nem segit.

Guy
--
Andras Korn <korn at chardonnay.math.bme.hu>
<http://chardonnay.math.bme.hu/~korn/> QOTD:
A Nap felesleges! Akkor vilagit, amikor amugy is vilagos van...
Zs
2004-11-12 15:05:47 UTC
Permalink
Hali!
Post by Horváth Ágoston János
Látható, hogy a kerekítés nem egészen működik, de legalábbis elég
furán. Ezzel eddig semmi gond sincs, a google egy egész halom oldalt
dob ki, ahol hasonló gondokat reportoltak. A gond ott kezdődik, hogy a
mysql team válasza az, hogy ők simán meghívják a libc round()
függvényét, így implementáció-függő, hogy mi fog történni.
Barbár megoldás, de a libtarsh -hoz hasonlóan írj egy könyvtárat C-ben,
ami implementálja a round() hívást és LD_PRELOAD -dal töltsd be
a mysql indítása elött. Ezzel így elkapod a libc elől a round() hívást
és úgy fogja csinálni, ahogy te szeretnéd.

De mint írom, ez elég barbár megoldás...

Üdv
Zsolt
Horváth Ágoston János
2004-11-12 15:12:20 UTC
Permalink
Post by Zs
Barbár megoldás, de a libtarsh -hoz hasonlóan írj egy könyvtárat C-ben,
ami implementálja a round() hívást és LD_PRELOAD -dal töltsd be
a mysql indítása elött. Ezzel így elkapod a libc elől a round() hívást
és úgy fogja csinálni, ahogy te szeretnéd.
De mint írom, ez elég barbár megoldás...
Pillanatnyilag kevésbé hat meg, hogy mennyire barbár megoldás,
egyszerűen működnie kell, minimális beavatkozással.
A gond a fentivel az, hogy tudtommal a statikus binárisok letojják
magasról, hogy mit bűvészkedsz a libekkel...
Palkó Péter
2004-11-13 08:58:08 UTC
Permalink
Post by Horváth Ágoston János
Post by Zs
Barbár megoldás, de a libtarsh -hoz hasonlóan írj egy könyvtárat C-ben,
ami implementálja a round() hívást és LD_PRELOAD -dal töltsd be
a mysql indítása elött. Ezzel így elkapod a libc elől a round() hívást
és úgy fogja csinálni, ahogy te szeretnéd.
De mint írom, ez elég barbár megoldás...
Pillanatnyilag kevésbé hat meg, hogy mennyire barbár megoldás,
egyszerűen működnie kell, minimális beavatkozással.
A gond a fentivel az, hogy tudtommal a statikus binárisok letojják
magasról, hogy mit bűvészkedsz a libekkel...
Kb. 3 éve írtam a mysql-nek, hogy a round() fügyvény rosszul kerekíti a
minusz tartományt, mert a round(-1.5)-öt -1 -re kerekítette. Azt vettem
észre,
hogy a következő kiadásokban már kijavították. Esetleg a mysql házatáján
kell
PÁSZTOR György
2004-11-13 16:58:54 UTC
Permalink
Hali!
Post by Palkó Péter
Kb. 3 éve írtam a mysql-nek, hogy a round() fügyvény rosszul kerekíti a
minusz tartományt, mert a round(-1.5)-öt -1 -re kerekítette. Azt vettem
észre,
Lehet, hogy én nem figyeltem jól az iskolában de emlékeim szerint
round(-1.5) /def -1 és round(1.5) pedig 2, szintén /def... (Ha netán nem
menne a miért... Csak abba gondolj bele, hogy egyébként hogy a rákba tudnád
fenntartani a round() függvény szép lépcsős formáját...)

Üdv:Gyur!
-- -------[ Free Software ISOs - http://www.fsn.hu/?f=download ]------- --
PÁSZTOR György e-mail: ***@fsn.hu
Free Software Network (FSN.HU) cell.: +3620 512 3335
Horváth Ágoston János
2004-11-16 16:06:48 UTC
Permalink
Mondjuk az is értelmes magyarázat, hogy a round(x):=-round(-x), nemde?
Pláne, ha mondjuk okos informatikus kollégák a pénzügyi összeg negatív
előjelében kódolták el, hogy ki-vagy bejövő összegről van szó. Képzeld
el, eladsz 3 db A-t és 2db B-t X összegért, majd mikor
visszavételezed, akkor mondjuk X-2 lesz az áruk... Mókás dolog :)


On Sat, 13 Nov 2004 17:58:54 +0100, PÁSZTOR György
Post by PÁSZTOR György
Hali!
Post by Palkó Péter
Kb. 3 éve írtam a mysql-nek, hogy a round() fügyvény rosszul kerekíti a
minusz tartományt, mert a round(-1.5)-öt -1 -re kerekítette. Azt vettem
észre,
Lehet, hogy én nem figyeltem jól az iskolában de emlékeim szerint
round(-1.5) /def -1 és round(1.5) pedig 2, szintén /def... (Ha netán nem
menne a miért... Csak abba gondolj bele, hogy egyébként hogy a rákba tudnád
fenntartani a round() függvény szép lépcsős formáját...)
Ugron Balazs
2004-11-12 23:40:07 UTC
Permalink
Hali,

na ezzel eljatszottam egy par orat (mysql src download, forditas, turas), de
----- Original Message -----
Sent: Friday, November 12, 2004 3:10 PM
Subject: mysql round()
[...]
create table test (valami decimal(5,2));
insert into test values (5.555);
[...]
dob ki, ahol hasonló gondokat reportoltak. A gond ott kezdődik, hogy a
mysql team válasza az, hogy ők simán meghívják a libc round()
függvényét, így implementáció-függő, hogy mi fog történni.
[...]
Tehát: tud-e valaki olyan lehetőséget, ami a libc round() működését
befolyásolná, vagy bármi más módon lehetővé tenné, hogy kicsikarjak
normális kerekítést a mysql-ből? Bármilyen megoldás érdekel, kivéve a
truncate, floor és ceiling, valamint egyéb SQL-függvények, mert
iszonyat kényelmetlen -és a projektünk jelenlegi állapotában
kivitelezhetetlen- minden queryt felülvizsgálni.
Eloszor is a mysql teamnek se kell mindent elhinni, mert a nagy francokat
hivjak ok libc round fuggvenyet, ugyanis az sprintf-et hivjak (ami szerintem
amugy eleg vicces).

Node ez mindegy, a problema oka abban rejlik, hogy az adott platformon
az 5.555 nem egeszen 5.555 a binaris abrazolas miatt, hanem 5.5549xxx.
Ez a kovetkezo peldaprogival feltehetoleg jol lathato (a mysql is nagyjabol
igy kerekit tablaba insertkor):

#include <stdio.h>

int main()
{
printf("%.40f\n", 5.555);
printf("%.2f\n", 5.555);
return 0;
}

Erdekes viszont hogy a

select round(5.555,2);

eredmenye helyes. Ennek pedig az az oka, hogy ott nem sprintf-elnek, hanem
olyan
modon szenvednek, aminel a konkret esetben a kerekitett erteket az

rint(5.555*100)/100

eredmenye hatarozza meg, ami (gondolom) azert ad helyes eredmenyt, mert itt
pont
az 5.555 binaris abrazolasanak a 100*-at nem lehet pontosan abrazolni (mert
.5-ot
pontosan lehet), igy az 5.5549xxx*100 = _pontosan_ 555.5, amire az rint
boldogan 556-ot
mond, igy a szazadresz korrekt eredmenyt nyujt.

Megoldasi lehetosegkent nekem kizarolag a mysql forras meghekkelese es az
ujraforditas
jut eszembe. Amennyiben erre adnad a fejed, akkor a konkret esetben a
forrasban a
sql/field.cc fileban az int Field_decimal::store(double nr) fuggvenyben
talalod
az insert-kor kerekitest vegzo hibas reszt, a round fuggveny hasznalatakor
meghivodo
kerekito cuccos pedig az sql/item_func.cc fileban a double
Item_func_round::val()

Remelem tudtam valamit segiteni,
Balazs
Horváth Ágoston János
2004-11-16 16:09:30 UTC
Permalink
Köszi, ez nagyon hasznos volt. Mondjuk nem gondoltam volna, hogy ilyen
bénaságok vannak benne. Bár amikor a libc -re hivatkoztak, miközben az
általuk készített static bináris is hibás volt, akkor kezdtem gyanút
fogni. :)

Azt hiszem, forrásból újrafordítás lesz belőle. Megyek, leporolom a
régi jó gcc2.95.4-et.
Köszönöm mindenkinek a segítséget.
Post by Ugron Balazs
na ezzel eljatszottam egy par orat (mysql src download, forditas, turas), de
Loading...