[mysql] Bit shift werkt in 4.1 maar niet in 5.0

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Heedless
  • Registratie: Januari 2006
  • Niet online
Ik heb een code die een gegeven PHP variabele vergelijkt met een veld in mijn database. Beide waarden zijn een kleur in de vorm van een int. Doormiddel van bit shifting kan ik de RGB waarde vinden en vergelijken.
Dit werkt perfect in Mysql 4.1 maar nu moet ik hetzelfde doen op een server met Mysql 5.1 en opeens werkt het niet meer. Heeft iemand enig idee hoe dit kan?

Deze code is vergelijkbaar met mijn code, en laat geeft wel een geldige colorDiff terug in 4.1 maar niet in 5.0
SQL:
1
2
3
4
"SELECT *, ABS((theColor >> 16 & 255) - ($myColor >> 16 & 255)) AS colorDiff 
                    FROM myTable
                    ORDER BY colorDiff ASC
                    LIMIT 1;"


Na wat testen merkte ik dat de bitwise operator zelf het gewoon doet, dit geeft bijvoorbeeld gewoon netjes 22 terug als colorDiff:

SQL:
1
2
3
4
"SELECT *, (1461616 >> 16 & 255) AS colorDiff 
                    FROM myTable
                    ORDER BY colorDiff ASC
                    LIMIT 1;"



Ik heb al geprobeerd om mijn velden van int( 8 ) naar bigInt( 8 ) of double( 8,0 ) te zetten, maar het blijft allemaal rare uitkomsten geven. De uitkomst kan soms bijvoorbeeld 0 zijn terwijl het eigenlijk 10 moet zijn, maar is soms ook opeens super hoog (1845147641742-achtig).

Acties:
  • 0 Henk 'm!

  • Nvidiot
  • Registratie: Mei 2003
  • Laatst online: 03-06 16:38

Nvidiot

notepad!

Kun je daar niet beter een Enum of een Set type voor gebruiken? http://dev.mysql.com/doc/refman/5.0/en/set.html

What a caterpillar calls the end, the rest of the world calls a butterfly. (Lao-Tze)


Acties:
  • 0 Henk 'm!

  • Infinitive
  • Registratie: Maart 2001
  • Laatst online: 25-09-2023
Dit soort berekeningen zou ik dan ook lekker door PHP laten doen! Laat je database de gegevens aandragen maar zorg voor hoe de data gepresenteerd wordt in de client.

Sowieso maak je nu je leven al extra moeilijk door de $myColor in je query te embedden.

putStr $ map (x -> chr $ round $ 21/2 * x^3 - 92 * x^2 + 503/2 * x - 105) [1..4]


Acties:
  • 0 Henk 'm!

  • Heedless
  • Registratie: Januari 2006
  • Niet online
Infinitive schreef op vrijdag 19 augustus 2011 @ 20:04:
Dit soort berekeningen zou ik dan ook lekker door PHP laten doen! Laat je database de gegevens aandragen maar zorg voor hoe de data gepresenteerd wordt in de client.
Ik zoek naar de kleur die het meest lijkt mij mijn kleur. Door bit shifting kan ik uit de int in de database een R, G en B vissen, en berekenen hoeveel de kleur verschilt van mijn gegeven kleurwaarde. Door vervolgens op dat verschil te sorteren krijg ik de record die er het meest op lijkt. Ik weet namelijk van te voren niet precies wat er in zit, dus roepen "ik wil DEZE waarde" kan niet, ik moet te pakken krijgen wat er het dichts bij ligt (wat toevallig hetzelfde zou kunnen zijn).

Zou ik dit in PHP willen doen dan moet ik eerst ALLE mogelijke opties uit de database halen en daar dan doorheen gaan loopen om te kijken welke er het meest op lijkt, wat nogal veel extra werk is. Ik heb altijd geleerd dat je van te voren moet beperken wat je opvraagt ipv zomaar alles pakken en kijken wat je eigenlijk nodig hebt.

[ Voor 8% gewijzigd door Heedless op 19-08-2011 20:13 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

De vraag is dan eerder waarom je in hemelsnaam de kleur als int opslaat als je toch met de verschillende componenten wilt rekenen in je database.

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.


Acties:
  • 0 Henk 'm!

  • Heedless
  • Registratie: Januari 2006
  • Niet online
.oisyn schreef op zaterdag 20 augustus 2011 @ 00:47:
De vraag is dan eerder waarom je in hemelsnaam de kleur als int opslaat als je toch met de verschillende componenten wilt rekenen in je database.
Nogmaals: het probleem is dat bit shifting niet werkt in MySQL 5.0 en ik daar een oplossing voor zoek. Dat kan namelijk ook handig zijn bij toekomstige projecten.

Maar misschien moet ik voor dit project inderdaad maar overstappen op een R G en B veld. Ik had het zo gedaan omdat ik nu per kleur maar 1 veld nodig heb ipv 3. Bij een grote hoeveelheid records en meerdere kleuren per record bespaar je daar een hoop ruimte mee. Maar de database is minder vol geworden dan ik had verwacht, dus waarschijnlijk maakt het weinig uit als ik er wat velden bij zet.
Bedankt voor het meedenken in elk geval.

Acties:
  • 0 Henk 'm!

  • frickY
  • Registratie: Juli 2001
  • Laatst online: 22-09 15:11
Is het niet dat je naast een upgrade naar Mysql5 ook te maken hebt met een PHP upgrade van 4.3 naar 5.0/5.3 ? Lijkt me namelijk veel aannemelijker dat je $myColor variabele niet (goed) geset is.
Of heb je de exacte query zoals die wordt uitgevoerd als eens ge-echoed?

Acties:
  • 0 Henk 'm!

  • Heedless
  • Registratie: Januari 2006
  • Niet online
Ik heb de query naar een log geschreven en hij klopt wel. Als ik hem volgens in phpMyAdmin direct invoer dan geeft hij op mijn server met MySql 4 het goede resultaat, maar op een server met MySql 5 niet. De database op MySql 5 is een kopie van die in 4, en alles lijkt precies hetzelfde ingesteld te zijn.
Als ik de tweede query van mijn beginpost uitvoer dan zie ik dat het bitshiften zelf wel werkt, maar zodra ik met het resultaat van die bitshift ga rekenen, dan komen er rare uitkomsten uit.
Reken ik handmatig de bitshift uit en zet ik deze uitkomst in de query, dan kan ik daar gewoon mee rekenen.

Maar ik ga het wel zo aanpakken dat het bitshiften niet meer nodig is; ik ben hier eigenlijk al te lang mee bezig.

[ Voor 7% gewijzigd door Heedless op 20-08-2011 11:29 ]


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Heedless schreef op zaterdag 20 augustus 2011 @ 11:16:
[...]

Maar misschien moet ik voor dit project inderdaad maar overstappen op een R G en B veld. Ik had het zo gedaan omdat ik nu per kleur maar 1 veld nodig heb ipv 3. Bij een grote hoeveelheid records en meerdere kleuren per record bespaar je daar een hoop ruimte mee.
Je gebruikt nu een int (-2147483648 tot 2147483647 of 0 tot 4294967295) zie ik? Een int neemt 4 bytes in de DB in beslag. Met een unsigned tinyint (0-255) gebruik je maar één byte per kleur, dus drie in totaal. Dus dát is zelfs kleiner. :)

Maar als je 't als unsigned medium-int (0 tot 16777215) opslaat maakt 't geen klap uit, aangezien die ook 3 bytes inneemt.

Kortom: voor de DB-grootte hoef je 't sowieso niet te laten, apart opslaan.

Acties:
  • 0 Henk 'm!

  • Jegorex
  • Registratie: April 2004
  • Laatst online: 03-09 23:24
Heedless schreef op zaterdag 20 augustus 2011 @ 11:28:
Als ik de tweede query van mijn beginpost uitvoer dan zie ik dat het bitshiften zelf wel werkt, maar zodra ik met het resultaat van die bitshift ga rekenen, dan komen er rare uitkomsten uit.
Als bitshiften werkt, dan is dat dus niet het probleem.

Acties:
  • 0 Henk 'm!

  • Heedless
  • Registratie: Januari 2006
  • Niet online
Als bitshiften werkt, dan is dat dus niet het probleem.
Maar zoals ik aangaf werkt het niet wanneer ik er vervolgens mee ga rekenen. Maar ik pas het wel aan zodat ik geen bit shifting meer nodig heb.

Bedankt in elk geval.

[ Voor 42% gewijzigd door Heedless op 20-08-2011 12:40 ]


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Wat is $myColor precies? Print de daadwerkelijke contents van die string is zoals je 'm aan MySQL voert?

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.


Acties:
  • 0 Henk 'm!

  • Heedless
  • Registratie: Januari 2006
  • Niet online
Ik heb inmiddels mijn code veranderd zodat ik direct met losse RGB waarden werk, en dat gaat prima. Dus qua werking is mijn probleem opgelost. Wat mij betreft kan dit topic dicht

@.oysin

$myColor is een RGB waarde als int. Zo staat 16114625 voor R 245, G 227, G 193.
Door bitshifting kan je die waarden er uit destileren
(16114625 >> 16) & 0xFF = R
(16114625 >> 8) & 0xFF = G
16114625 & 0xFF = B

Met met query is niets mis: in mijn log zie ik de goede query staan en in MySQL 4 werkt het ook gewoon. MySQL 5 lijkt niet goed om te kunnen gaan met bitshiften.

Acties:
  • 0 Henk 'm!

  • jan-marten
  • Registratie: September 2000
  • Laatst online: 21-09 20:24
Volgens mij is het de volgorde waarin de operators staan het verschil in 4 en 5.
Bij mij werkt het volgende namelijk wel goed:

ABS((16114625 >> 16) & 255 - (16464627 >> 16) & 255)

Je doet dus een AND met 16 & 255 ipv de uitkomst van de bitshift te and-en met 255.

Acties:
  • 0 Henk 'm!

  • Janoz
  • Registratie: Oktober 2000
  • Laatst online: 21-09 02:21

Janoz

Moderator Devschuur®

!litemod

Heedless schreef op dinsdag 23 augustus 2011 @ 14:03:
@.oysin

$myColor is een RGB waarde als int. Zo staat 16114625 voor R 245, G 227, G 193.
Door bitshifting kan je die waarden er uit destileren
(16114625 >> 16) & 0xFF = R
(16114625 >> 8) & 0xFF = G
16114625 & 0xFF = B

Met met query is niets mis: in mijn log zie ik de goede query staan en in MySQL 4 werkt het ook gewoon. MySQL 5 lijkt niet goed om te kunnen gaan met bitshiften.
Ik denk dat .oisyn dondersgoed weet hoe 3 bytes eruit zien. Zijn vraag kwam meer neer op:

"Wat krijg je als je echo $myColor doet?"

Ken Thompson's famous line from V6 UNIX is equaly applicable to this post:
'You are not expected to understand this'


Acties:
  • 0 Henk 'm!

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

jan-marten schreef op dinsdag 23 augustus 2011 @ 15:58:
Volgens mij is het de volgorde waarin de operators staan het verschil in 4 en 5.
Bij mij werkt het volgende namelijk wel goed:

ABS((16114625 >> 16) & 255 - (16464627 >> 16) & 255)

Je doet dus een AND met 16 & 255 ipv de uitkomst van de bitshift te and-en met 255.
Ik denk niet dat de volgorde gewijzigd is. Sowieso boeit het in de voorbeelden die hier in de topic staan ook niet. De AND met 255 is namelijk overbodig in het geval van de most significant byte in een 24 bits getal, en 16 AND 255 is gewoon 16.

Daarom denk ik dat de fout gewoon zit in het opbouwen van de query, en niet in het uitvoeren ervan door mysql

[ Voor 8% gewijzigd door .oisyn op 24-08-2011 20:16 ]

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.


  • jan-marten
  • Registratie: September 2000
  • Laatst online: 21-09 20:24
Hmz, nu je het zegt. Ik vond het al een beetje vreemd. De haakjes zijn ook niet nodig (zie ook MySQL 5 operator precedence).

Blijft de vraag dus wat er in de de velden 'theColor' en '$myColor' staat.

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 22-09 16:37

.oisyn

Moderator Devschuur®

Demotivational Speaker

Interessant, volgens de docs is het resultaat van een shift altijd een unsigned bigint. Dat verklaart iig waarom je af en toe van die grote getallen krijgt - je rekent met unsigned getallen dus het resultaat is nooit negatief. Dit verklaart echter nog niet waarom het in mysql 4 wel goed ging, want dat gedrag is niet gewijzigd.

.edit: sinds 5.5.5 is het gedrag van substraction overigens wel gewijzigd:
Subtraction between integer values, where one is of type UNSIGNED, produces an unsigned result by default. Prior to MySQL 5.5.5, if the result would otherwise have been negative, it becomes the maximum integer value:
mysql> SET sql_mode = '';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| 18446744073709551615 |
+-------------------------+
As of MySQL 5.5.5, if the result would otherwise have been negative, an error results:
mysql> SET sql_mode = '';
Query OK, 0 rows affected (0.00 sec)

mysql> SELECT CAST(0 AS UNSIGNED) - 1;
ERROR 1690 (22003): BIGINT UNSIGNED value is out of range in '(cast(0 as unsigned) - 1)'
If the NO_UNSIGNED_SUBTRACTION SQL mode is enabled, the result is negative:
mysql> SET sql_mode = 'NO_UNSIGNED_SUBTRACTION';
mysql> SELECT CAST(0 AS UNSIGNED) - 1;
+-------------------------+
| CAST(0 AS UNSIGNED) - 1 |
+-------------------------+
| -1 |
+-------------------------+
If the result of such an operation is used to update an UNSIGNED integer column, the result is clipped to the maximum value for the column type, or clipped to 0 if NO_UNSIGNED_SUBTRACTION is enabled. If strict SQL mode is enabled, an error occurs and the column remains unchanged.
Maar dit verklaart nog altijd niet waarom het eerst goed ging.

.edit2: hmm, had je in 4 soms NO_UNSIGNED_SUBTRACTION aan staan en in 5 niet?

[ Voor 4% gewijzigd door .oisyn op 25-08-2011 12:05 ]

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.

Pagina: 1