[java] lexografische string van primitives/numbers

Pagina: 1
Acties:
  • 332 views sinds 30-01-2008
  • Reageer

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Ik zit met het volgende probleem. Ik moet getallen in een searchengine in de juiste volgorde kunnen opzoeken. Helaas kan de searchengine (Lucene) alleen werken met Strings en daarom moet ik de getallen omzetten naar Strings die lexografisch in dezelfde volgorde staan als ze getalsmatig staan.

Stel dat ik 2 en 10 heb. Als ik dit in de searchengine zou plaatsen, dan zou 2 na 10 staan (2 staat later in het woordenboek dan 10). Daarom moet ik 2 dus bv aanvullen met 0`en: 02. 02 staat eerder in het woordenboek dan 10. Het probleem is dat ik nergens een handige functie heb kunnen vinden die dit voor mij doet (ik ben lui). Ik heb zelf al een in elkaar gezet voor gehele getallen maar ik zit een beetje met de gebroken getallen.

Ik kan hiervoor wel een oplossing bedenken, maar ik zoek eigelijk naar een functie die dit probleem netjes voor mij oplost. *scheelt me veel tijd*. Dus wie weet een oplossing voor dit probleem?

Verwijderd

Java:
1
2
3
4
5
6
7
8
    public String fixLength(double source, int length){
        String returnString = "";
        returnString += source;
        while (returnString.indexOf('.') < length){
            returnString = "0"+ returnString;
        }
        return returnString;
    }


fixLength(3.3, 3) -> "003.3"

Of heb ik het verkeerd begrepen en is dit veel te simpel gedacht?

  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:47

.oisyn

Moderator Devschuur®

Demotivational Speaker

Begrijp ik het verkeerd of plaats je hier een scriptrequest, Alarmnummer?

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.


  • momania
  • Registratie: Mei 2000
  • Laatst online: 17:09

momania

iPhone 30! Bam!

Kan je niet met StringUtils.leftPad() uit de voeten?

Neem je whisky mee, is het te weinig... *zucht*


  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
.oisyn schreef op donderdag 04 augustus 2005 @ 16:38:
Begrijp ik het verkeerd of plaats je hier een scriptrequest, Alarmnummer?
Mwuah.. script request vind ik wel meevallen. Ik zoek naar een manier om eenvoudig van een number naar een goeie lexografische representatie te komen. Ik zit er al een paar uur achter en tot zover heb ik weinig bruikbaars gevonden. Dus vandaar mijn vraag.

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
Verwijderd schreef op donderdag 04 augustus 2005 @ 16:35:
Java:
1
2
3
4
5
6
7
8
    public String fixLength(double source, int length){
        String returnString = "";
        returnString += source;
        while (returnString.indexOf('.') < length){
            returnString = "0"+ returnString;
        }
        return returnString;
    }


fixLength(3.3, 3) -> "003.3"

Of heb ik het verkeerd begrepen en is dit veel te simpel gedacht?
Je zit sowieso nog met de macht en de radix die vertaald moeten worden.

Bv 1.5e12.

Als je hier geen goeie lexografische string van maakt krijg je onzin.

  • alienfruit
  • Registratie: Maart 2003
  • Laatst online: 03-05 23:13

alienfruit

the alien you never expected

Kan je niet wat doen met de lexografische verschillen die een compareTo() teruggeeft?

  • Alarmnummer
  • Registratie: Juli 2001
  • Laatst online: 09-07-2024
alienfruit schreef op donderdag 04 augustus 2005 @ 17:18:
Kan je niet wat doen met de lexografische verschillen die een compareTo() teruggeeft?
Ik zie niet in hoe ik op basis daarvan een goeie lexografische string terug krijg. Verder ben ik even aan het stoeien met de DecimalFormat. Ik denk dat ik daarmee wel iets kan maken.

  • DaCoTa
  • Registratie: April 2002
  • Laatst online: 15:55
Ik ken het probleem, na vele variaties ben ik blijven steken op:
Java:
1
2
3
4
5
    static final String PADDER = "0000000000";

    public String pad(String s) {
      return PADDER.substring(s.length()) + s;
    }

Als je idd echt met exponenten en radix wilt gaan werken, tja, dan gaat het veel ingewikkelder worden. Je moet iig alles naar een uniforme variant omschrijven, want je zou dan dus ook een schrijfwijze met exponent en zonder die gelijke waarde hebben, ook bij elkaar terug willen vinden.

Een mogelijke uniforme variant heeft iig de exponent vooraan staan, ook gepad. Ik weet niet wat de maximale exponent van je getallen, maar dan krijg je dus zoiets als:
code:
1
000000001e00000000033

Waarbij de exponent 1 is en 33 dat andere ding, oftewel, het natuurlijke getal 33.

edit:
Mantissa... Dankjewel.

[ Voor 77% gewijzigd door DaCoTa op 04-08-2005 17:47 ]


  • .oisyn
  • Registratie: September 2000
  • Laatst online: 12:47

.oisyn

Moderator Devschuur®

Demotivational Speaker

Alarmnummer schreef op donderdag 04 augustus 2005 @ 17:20:
[...]

Ik zie niet in hoe ik op basis daarvan een goeie lexografische string terug krijg. Verder ben ik even aan het stoeien met de DecimalFormat. Ik denk dat ik daarmee wel iets kan maken.
Ik weet niet hoe leesbaar je getallen moeten blijven, maar anders zou je alle getallen kunnen converteren naar wetenschappelijke notatie ([-]x.yyyEzzz), en dan het exponent gedeelte juist tussen het teken en de mantissa zetten (dus iets als: [-]Ezzz;x.yyy), waarbij je het exponent vastzet op een aantal decimalen (3 moet genoeg zijn imho). Op die manier zijn je getallen altijd lexografisch goed geordend, en het maakt niet uit hoeveel significante cijfers de mantissa beslaat.

[ Voor 8% gewijzigd door .oisyn op 04-08-2005 17:45 ]

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.


  • Daos
  • Registratie: Oktober 2004
  • Niet online
Je kan je de bytes van je getal omzetten naar een string. Dit moet in de BigEndian volgorde (belangrijkste byte eerst).

De unsigned integers zijn al op volgorde. Hiervoor hoef je niets extra te doen.

De signed integers zijn in 2's complement. Om de volgorde goed te houden moet je de sign-bit inverteren. Neem bijvoorbeeld een 4 bits signed integer:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
getal = int  = nieuw
-8    = 1000 = 0000
-7    = 1001 = 0001
-6    = 1010 = 0010
-5    = 1011 = 0011
-4    = 1100 = 0100
-3    = 1101 = 0101
-2    = 1110 = 0110
-1    = 1111 = 0111
 0    = 0000 = 1000
 1    = 0001 = 1001
 2    = 0010 = 1010
 3    = 0011 = 1011
 4    = 0100 = 1100
 5    = 0101 = 1101
 6    = 0110 = 1110
 7    = 0111 = 1111


De floatingpoint getallen zijn in een soort signed-magnitude. Om de volgorde goed te houden moet je de negatieve getallen inverteren en bij de positieve alleen de signbit 1 maken. Neem bijvoorbeeld floatingpoint getal met 1 sign bit, 2 exponent bits (bias = 1) en 1 mantissa bit:
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
getal = fp   = nieuw
-6    = 1111 = 0000
-4    = 1110 = 0001
-3    = 1101 = 0010
-2    = 1100 = 0011
-1.5  = 1011 = 0100
-1    = 1010 = 0101
-0.75 = 1001 = 0110
-0.5  = 1000 = 0111
 0.5  = 0000 = 1000
 0.75 = 0001 = 1001
 1    = 0010 = 1010
 1.5  = 0011 = 1011
 2    = 0100 = 1100
 3    = 0101 = 1101
 4    = 0110 = 1110
 6    = 0111 = 1111


[edit]
In het echt ziet het er zo uit:
Java:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
public class Pack {
  public static String packUnsignedLong(long u) {
    String hex = Long.toHexString(u);
    StringBuffer fill = new StringBuffer();
    fill.setLength(16 - hex.length());
    for (int i = 0; i < fill.length(); i++)
      fill.setCharAt(i, '0');

    return fill + hex;
  }

  public static long unpackUnsignedLong(String s) {
    int hlength = s.length() / 2;
    long bitsh = Long.parseLong(s.substring(0, hlength), 16);
    long bitsl = Long.parseLong(s.substring(hlength), 16);
    long bits = bitsh << 32 | bitsl;

    return bits;
  }

  public static String packLong(long l) {
    long bits = l;

    bits ^= 1L << 63;

    return packUnsignedLong(bits);
  }

  public static long unpackLong(String s){
    long bits = unpackUnsignedLong(s);

    bits ^= 1L << 63;

    return bits;
  }

  public static String packDouble(double d) {
    long bits = Double.doubleToLongBits(d);

    if (bits < 0)
      bits = ~bits;
    else
      bits |= 1L << 63;

    return packUnsignedLong(bits);
  }

  public static double unpackDouble(String s){
    long bits = unpackUnsignedLong(s);

    if (bits >= 0)
      bits = ~bits;
    else
      bits &= ~(1L << 63);

    return Double.longBitsToDouble(bits);
  }

  public static void main(String[] args) {

    double x = 1.0;
    String s = packDouble(x);
    double y = unpackDouble(s);

    long u = 1;
    String t = packLong(u);
    long v = unpackLong(t);

    System.out.println(x);
    System.out.println(s);
    System.out.println(y);

    System.out.println(u);
    System.out.println(t);
    System.out.println(v);

  }
}

[ Voor 56% gewijzigd door Daos op 04-08-2005 21:04 ]

Pagina: 1