double-Werte in einem Intervall

Kurze Frage an euch, und hab ich in 'nem anderen Forum gelesen:
Wie viele double-Werte gibt es zwischen 1.0 (eingeschlossen) und 3.0 (ausgeschlossen) ?

Und, damit es nicht zu leicht ist:
Wie viele double-Werte gibt es zwischen 1.0 (eingeschlossen) und 5.0 (ausgeschlossen) ?

Das bezieht sich auf Java, und geschaut hab ich auch hier: floating point - Float and double datatype in Java - Stack Overflow .

Vielen Dank für JEDE Antwort/Erklärung. Alles könnte „nützlich“ sein. :smile:

(Für zwischen 0 und 1 hätte ich schon eine Idee, aber nicht für Obige).

Hier der Fall zwischen 0 und 1:

Dort steht auch, warum andere Intervalle schwierig sind. Theoretisch. Praktisch sind sie einfach. Man braucht nur ein paar Zeilen code…

public class CountingDoubles
{
    public static void main(String[] args)
    {
        System.out.println(howManyAreThereBetween(1.0, 3.0));
        System.out.println(howManyAreThereBetween(1.0, 5.0));
    }
    
    private static long howManyAreThereBetween(
        double minInclusive, double maxExclusive)
    {
        double d = minInclusive;
        long n = 0;
        while (d < maxExclusive)
        {
            n++;
            d = Math.nextUp(d);
        }
        return n;
    }
}

und vieeeel Geduld :smiley:

1 Like

Jae, das deckt sich mit dem, was ich vermutet hatte… Allerdings ist die Erklärung auf SO auch nicht „trivial“.

Danke für CountingDoubles, main und howManyAreThereBetween.

Sooo viel Geduld hab ich allerdings nicht. :sweat_smile:

SO scheint wirklich viele Fragen zu enthalten…

Man kann sich aber auch anschauen wie nextUp funktioniert.

http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/sun/misc/FpUtils.java?av=f

Über doubleToLongBits und aus dem Long mit toBinaryString dürfte man die Binäre Darstellung bekommen, wenn man da dann ein bischen rumschaut, dann dürfte man auch von der binären Darstellung, gerade wenn man mit nextUp ein bischen Zählt auf eine Idee kommen wie man das ganze hochrechnen könnte.
Wenn ich das richtig sehe, wird ja hauptsächlich die Mantisse hochgezählt, bis man einen neuen Exponenten braucht. Da geht dann das Spiel von vorne los.

Das ist richtig. Vermutlich(*) wird “intern” so hochgezählt (hab nicht in den Source geschaut):

d = Double.longBitsToDouble(Double.doubleToRawLongBits(d) + 1L);

(d ist ein double, der hochgezählt werden soll)
wobei es dabei eigentlich noch einiges zu beachten gilt, u. A. … mit Überlauf usw.


(*): Nicht nur vermutlich, so steht’s auch bei SO.


Jeden Exponentenübergang sollte man sich whrs. anschauen. Wann im und wann nicht im Intervall

Hm, da hab ich ja was angestoßen. :sweat_smile:

Das Tool hilft wahrscheinlich auch: IEEE-754 Floating Point Converter

Noch schönen Tag.

1 Bit Vorzeichen, 11 Bit Exponent und 52 Bit Mantisse…

Wie wäre es mit log(abs(d)) * 2^52/log(2) - 1?

Die 3 ist daraus nicht ersichtlich - vielleicht meinst du auch die 5. Ich weiß es nicht.

Tja… dann überleg mal…

Aber irgendwo hast du Recht. Für Intervalle fehlt da noch ein zweiter Term.

Ich hab gar nix von einem unvollständigen Term geschrieben. Lediglich, dass ich daraus nicht erkennen kann, worauf du dich beziehst.

Das kann an mir liegen, und/oder nicht viel Erfahrung auf dem Gebiet.

Ich hätte jetzt die “wenigen” Exponentenübergangsfälle ( oder heißt es Exponentenübergängefälle? ) untersucht. Jedenfalls vielen Dank für die Antwort.

Alles was du wissen musst, ist doch, dass für jeden der 2^11 Exponenten 2^52 Mantissen zur Verfügung stehen (mit Vorzeichen-Bit 2^53, aber das habe ich weggelassen). Nun setzt du d=3 bzw. 5, rechnest und anschließend rechnest du nochmal mit d=1 (2. Term). Zuletzt ziehst du den höheren Wert vom niedrigeren ab. Für Inklusivwerte lässt du die -1 weg.

Meine Ergebnisse:

1 <= 3:  6755399441055744
3 <= 5:  3377699720527872
1 <= 5: 10133099161583616

import java.lang.Math;

public class CountNumbers
{
  public static void main(String[] args)
  {
    double lowerBound = 3.0;
    double upperBound = 5.0;
    long lowerAsLongBits = Double.doubleToLongBits(lowerBound);
    long upperAsLongBits = Double.doubleToLongBits(upperBound);
    long result = upperAsLongBits - lowerAsLongBits;
    System.out.println(lowerAsLongBits);
    System.out.println(upperAsLongBits);
    System.out.println(result);    
  }
}

Zumindest für alle Positiven Zahlen bei denen upperBound < lowerBound ist. Bei Zahlen kleiner 1 bin ich mir noch etwas unschlüssig.
Da das Format ja so gestrickt ist, dass wenn es bei der Mantisse zu einem überlauf käme, dieser ja eigentlich den Exponenten erhöht und dieser ja links von der Mantisse steht, dürfte das einigermassen hinhauen.

Alle Angaben ohne Gewähr. Würde aber auch gerne die Antwort sehen die CB hat, falls er da mal ein Ergebnis bekommt. Mit den RawBits kommt, übrigens das selbe raus.

Moin,

ich hatte über float hochgezählt, dann im Verhältnis 23 zu 52 (Mantissebits) die Anzahl der double-Werte im Intervall hochgerechnet; in’ner Annahme, es gibt für die Werte genausoviele Exponenten"gruppen" in float wie in double.

Es gilt glaub’ ich:
a^b für alle b>=0, < (a+1)^c für alle c>=0. (b und c sind Mantisse(n).)

(Wenn sich der Exponent erhöht, sind alle _ Werte größer…)


Aber das ist weit aus dem Fenster gelehnt. :frowning: