[mysql] Mathematische berekening geeft foutieve uitkomst.

Pagina: 1
Acties:

  • cyberstalker
  • Registratie: September 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
Ik heb een probleem met het uitvoeren van een berekening op een float in een tabel.

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
mysql> describe mDeduction;
+-------------+--------------+------+-----+-------------------+----------------+
| Field       | Type         | Null | Key | Default           | Extra          |
+-------------+--------------+------+-----+-------------------+----------------+
| mDid        | int(11)      | NO   | PRI | NULL              | auto_increment |
| status      | tinyint(4)   | NO   |     | 0                 |                |
| replacedBy  | int(11)      | NO   |     | -1                |                |
| fk_pid      | int(11)      | NO   |     | 0                 |                |
| date        | date         | NO   |     | 0000-00-00        |                |
| amount      | float        | NO   |     | 0                 |                |
| unit        | varchar(20)  | NO   |     |                   |                |
| type        | varchar(20)  | NO   |     |                   |                |
| description | varchar(255) | NO   |     |                   |                |
| owner_id    | int(11)      | NO   |     | 0                 |                |
| timestamp   | timestamp    | NO   |     | CURRENT_TIMESTAMP |                |
+-------------+--------------+------+-----+-------------------+----------------+

mysql> select amount, amount / 0.225 from mDeduction where mDid = 3;
+--------+-----------------+
| amount | amount / 0.225  |
+--------+-----------------+
|   0.45 | 1.9999999470181 |
+--------+-----------------+
1 row in set (0.00 sec)
Iedereen die de basisschool heeft gevolgd weet natuurlijk dat 0.45 / 0.225 2 moet zijn. Hoe kan ik deze berekening werkend krijgen?

Ik heb al op google zitten zoeken naar functies als cast, maar zonder een oplossing te vinden.

Ik ontken het bestaan van IE.


  • TeeDee
  • Registratie: Februari 2001
  • Laatst online: 10:26

TeeDee

CQB 241

Je zit dus met een Round probleem? Of Floating Point Precision.

Misschien iets met Ceiling / Floor. Of zoals RobIII zegt het e.e.a. in een decimal gooien.

na zelf veel gezeik te hebben gehad met dit soort vuighe zaken, probeer ik zoveel mogelijk floats te vermijden. Pas als het echt nodig is :)

[ Voor 66% gewijzigd door TeeDee op 02-04-2007 14:16 ]

Heart..pumps blood.Has nothing to do with emotion! Bored


  • RobIII
  • Registratie: December 2001
  • Niet online

RobIII

Admin Devschuur®

^ Romeinse Ⅲ ja!

(overleden)
cyberstalker schreef op maandag 02 april 2007 @ 14:07:
Iedereen die de basisschool heeft gevolgd weet natuurlijk dat 0.45 / 0.225 2 moet zijn.
Iedereen die weet hoe floating points werken weet dat dat niet zo is ;)
Misschien dat je een Decimal kunt toepassen i.p.v. een float?

[ Voor 8% gewijzigd door RobIII op 02-04-2007 14:13 ]

There are only two hard problems in distributed systems: 2. Exactly-once delivery 1. Guaranteed order of messages 2. Exactly-once delivery.

Je eigen tweaker.me redirect

Over mij


  • cyberstalker
  • Registratie: September 2005
  • Niet online

cyberstalker

Eersteklas beunhaas

Topicstarter
RobIII schreef op maandag 02 april 2007 @ 14:11:
[...]

Iedereen die weet hoe floating points werken weet dat dat niet zo is ;)
Misschien dat je een Decimal kunt toepassen i.p.v. een float?
Het probleem is dat ik de database niet heb ontworpen. Het gaat hier om allemaal records die al bestaan. Vandaar dat ik al naar een manier aan het zoeken ben om dit om te zetten.

Ik wil hier checken of de bedragen een veelvoud zijn van 22,5 cent. Dit doe ik door het geheel te delen door 0.225, en te kijken of dat hetzelfde geeft als ik daar een FLOOR omheen zet.

SQL:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
SELECT
    mDid,
    fk_pid,
    date,
    amount,
    CEIL(amount / 0.225),
    FLOOR(amount / 0.225),
    amount / 0.225,
    owner_id
FROM
    mDeduction
WHERE
    replacedBy              =       -1                    AND
    description             LIKE    '%consumptie%'        AND
    CEIL(amount / 0.225)    >       FLOOR(amount / 0.225)

[ Voor 39% gewijzigd door cyberstalker op 02-04-2007 14:19 ]

Ik ontken het bestaan van IE.


  • KabouterSuper
  • Registratie: September 2005
  • Niet online
round(1000*amount)/225 als je weet dat je amount max 2 cijfers achter de komma heeft.....ik kan het nu niet controleren (ik heb hier alleen Oracle databases ), maar wellicht werkt het.

When life gives you lemons, start a battery factory


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

For once and for all

Geldbedragen sla je niet op met floating point getallen!!!



Dus... probeer een ander datatype :)

.edit: even gemist dat je de database niet zelf aan kunt passen. Wellicht kun je naar decimal casten voor je de berekening doet?

[ Voor 33% gewijzigd door .oisyn op 02-04-2007 15:03 ]

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • KabouterSuper
  • Registratie: September 2005
  • Niet online
En als het over aandelen koersen gaat? Wel een bedrag, maar toch niet handig om het af te ronden, zeker niet als je het wilt converteren naar andere valuta.

When life gives you lemons, start a battery factory


  • igmar
  • Registratie: April 2000
  • Laatst online: 30-11 18:38

igmar

ISO20022

cyberstalker schreef op maandag 02 april 2007 @ 14:07:
Iedereen die de basisschool heeft gevolgd weet natuurlijk dat 0.45 / 0.225 2 moet zijn. Hoe kan ik deze berekening werkend krijgen?
Het getal 2 bestaan niet als floating point getal. Of je database model aanpassen, of opvangen in je code.

  • kenneth
  • Registratie: September 2001
  • Niet online

kenneth

achter de duinen

KabouterSuper schreef op maandag 02 april 2007 @ 14:30:
En als het over aandelen koersen gaat? Wel een bedrag, maar toch niet handig om het af te ronden, zeker niet als je het wilt converteren naar andere valuta.
Dan gebruik je toch 'n ander fixed point datatype?

In ieder geval ...

niet met floating point getallen



;)

Look, runners deal in discomfort. After you get past a certain point, that’s all there really is. There is no finesse here.


  • .oisyn
  • Registratie: September 2000
  • Nu online

.oisyn

Moderator Devschuur®

Demotivational Speaker

KabouterSuper schreef op maandag 02 april 2007 @ 14:30:
En als het over aandelen koersen gaat? Wel een bedrag, maar toch niet handig om het af te ronden, zeker niet als je het wilt converteren naar andere valuta.
Ik zeg niet dat je gehele getallen moet gebruiken, ik zeg alleen dat je geen drijvende komma moet gebruiken. Een vaste komma bestaat bijvoorbeeld ook (zoals het Decimal datatype)
igmar schreef op maandag 02 april 2007 @ 14:31:

Het getal 2 bestaan niet als floating point getal. Of je database model aanpassen, of opvangen in je code.
Jawel hoor. Sterker nog, alle gehele getallen (tot een bepaalde precisie) bestaan als floating point getallen. Het is de 0.45 die roet in het eten gooit, die bestaat idd niet

Give a man a game and he'll have fun for a day. Teach a man to make games and he'll never have fun again.


  • The Eagle
  • Registratie: Januari 2002
  • Laatst online: 01-12 21:45

The Eagle

I wear my sunglasses at night

Wellicht dat de TS geholpen is met een praktijkvoorbeeldje :)

Ik ben momenteel zelf beheerder van een PeopleSoft Financials 8.8 systeem. Zwaar ERP-systeem, kan wisselkoersen etc allemaal aan. Is ook US GAAP en SOx compliant enzo, dus weet 100% zeker dat ze het in mijn systeempje goed geimplementeerd hebben :)

Hier is het iig zo dat alle bedragen (ongeacht of dat nou local of foreign currency is) opgeslagen worden in een veld met datatype NUMBER. NUMBER (26,3) om precies te zijn. Wisselkoersen worden opgeslagen als NUMBER (15,8), die hebben dus iets meer cijfers achter de komma :P

Betreft hier overigens een Oracle 9 database :)

Al is het nieuws nog zo slecht, het wordt leuker als je het op zijn Brabants zegt :)


  • MrBucket
  • Registratie: Juli 2003
  • Laatst online: 29-10-2022
cyberstalker schreef op maandag 02 april 2007 @ 14:15:
[...]
Ik wil hier checken of de bedragen een veelvoud zijn van 22,5 cent. Dit doe ik door het geheel te delen door 0.225, en te kijken of dat hetzelfde geeft als ik daar een FLOOR omheen zet.
Trucje: 9 / 0.225 = 40, oftewel x is een veelvoud van 0.225 als x * 40 een veelvoud van 9 is (dus als (x * 40) mod 9 = 0).

Dit lost nog steeds het probleem van de imprecieze opslag niet op, maar in ieder geval kun je de berekening dan zonder preciesieverlies uitvoeren.

Evt. volgend trucje wat zou moeten werken (als je bijvoorbeeld zeker weet dat de eerste 3 decimalen achter de komma altijd correct zijn):
(FLOOR(x * 40 * 1000) mod (9* 1000)) = 0

  • ACM
  • Registratie: Januari 2000
  • Niet online

ACM

Software Architect

Werkt hier

cyberstalker schreef op maandag 02 april 2007 @ 14:15:
Het probleem is dat ik de database niet heb ontworpen. Het gaat hier om allemaal records die al bestaan. Vandaar dat ik al naar een manier aan het zoeken ben om dit om te zetten.
Je hebt hem niet ontworpen, maar mag je hem (persoonlijke rechten) ook niet aanpassen?
Want mysql kan de meeste datatypeconversies gewoon op bestaande data uitvoeren (zeker van float naar decimal/numeric bij dergelijke getallen). Dus je zou er nu een decimal/numeric van kunnen maken met verder minimale (geen?) wijzigingen aan je code.
Pagina: 1