Ich bin nicht bereit, ein genaues Ergebnis über den Gleitkomma-Cast zu garantieren, es sei denn, die Mantisse hat genug Bits, um alle ganzzahligen Werte genau darzustellen. Zum Beispiel, betrachte y=9223372036854775807 und x = (y div 10) - 1 = 922337203685477579. wobei "div" ganzzahlige Division ist. x/y ist 0,09999999999999999981568563067746..., aber mit Doubles bekommst du >= 0,1. Dies ist ein Ergebnis davon, dass Doubles nur 52 Stellen der Genauigkeit in der Signifikanten haben (während y 61 Bits und x ungefähr 58 benötigt)
Sie können möglicherweise eine 80-Bit- oder 128-Bit-FP-Genauigkeit verwenden, in welchem Fall Sie die richtige Antwort erhalten würden, weil die Mantisse >=64 Bit (ULL sind 64 Bit, richtig?) wäre und so könnten Sie die Zahlen verlustfrei darstellen.
Ich würde mit einer Approximation beginnen (entweder mit ganzzahliger oder FP-Arithmetik) und dann eine Testmultiplikation durchführen, um zu sehen, ob die Antwort 1 weniger oder mehr sein sollte. Der Schlüsselgedanke ist, dass Sie immer noch zwei möglicherweise überlaufene Ganzzahlen vergleichen können, solange Sie wissen, dass der Unterschied zwischen den beiden Mengen weniger als die Hälfte der maximalen vorzeichenlosen Ganzzahl beträgt. Diese Art von Vergleichstechnik ist notwendig, wenn z.B. TCP-Sequenznummern überlaufen.
Falls Sie nur ganzzahlige Arithmetik verwenden möchten, funktioniert die unten stehende Funktion "fdd(x,y)". Ich habe ein main() hinzugefügt, um einige Ergebnisse zu zeigen:
#include
using namespace std;
typedef unsigned char ull; // ändern Sie char in einen beliebigen integralen Typ z.B. long long
const ull maxull=(ull)-1;
const ull halfull = maxull/2;
typedef unsigned long long asint;
// x = X mod (maxull+1), y= Y mod (maxull+1). wir kennen nur x und y
// wenn wir annehmen, dass |X-Y|x;
}
// vorausgesetzt x10 ist, um eine spätere Division durch 0 zu vermeiden
ull r=y/10;
if (r*10==y) return x/r;
ull ub=x/(r+1); // ub >= 10x div y (ohne Überlauf)
ull x10=x*10; // Überlauf zulassen
cout<<"ub="<<(asint)ub<<" x10="<<(asint)x10<<" r="<<(asint)r<<" ";
return less_mod_near(x10,ub) ? ub-1 : ub;
// den Fall, dass 10 gerade in y passt, haben wir bereits abgedeckt
}
int pdd(ull x, ull y,ull mustbe)
{
ull d=fdd(x,y);
cout << (asint)x << '/' << (asint)y << " = ." << (asint)d << "...";
if (d!=mustbe) cout << " (sollte "<<(asint)mustbe<<" sein)";
cout<
`Ausgabe:
0/1 = .0...
1/2 = .5...
11/101 = .1...
10/101 = .0...
ub=7 x10=234 r=6 49/69 = .7...
ub=7 x10=244 r=6 50/69 = .7...
ub=6 x10=224 r=6 48/69 = .6...
160/200 = .8...
161/200 = .8...
159/200 = .7...
ub=9 x10=236 r=25 254/255 = .9...`