Wenn 2 Zahlen angegeben werden, wobei A <= B
beispielsweise A = 9
und B = 10
sagen, versuche ich den Prozentsatz zu erhalten, wie kleiner A mit B verglichen wird. Ich muss den Prozentsatz als int
haben, z. Wenn das Ergebnis 10,00% ist, sollte die int
1000 sein.
Hier ist mein Code:
%Vor% Mein Code gibt 999 statt 1000 zurück. Einige Genauigkeit in Bezug auf die Verwendung von double
ist verloren.
Gibt es eine Möglichkeit, in meinem Fall Genauigkeit zu verlieren?
Scheint, dass die Formel, nach der Sie suchen,
ist %Vor%Die Idee ist, alle Berechnungen in ganzen Zahlen durchzuführen und die Division zu verzögern.
Um die Rundungshälfte des Nenners zu machen, wird vor der Division hinzugefügt (andernfalls erhalten Sie Kürzung in der Division und somit obere Rundung wegen 100% -x)
Zum Beispiel mit A = 9 und B = 11 ist der Prozentsatz 18.18181818 ... und die Rundung 18.18, die Berechnung ohne Rundung würde 1819 anstelle des erwarteten Ergebnisses 1818 ergeben.
Beachten Sie, dass die Berechnung in ganzen Zahlen erfolgt, sodass bei großen Werten von A
und B
das Risiko eines Überlaufs besteht. Wenn beispielsweise int
32 Bit ist, dann kann A
bis zu etwa 200000 sein, bevor bei der Berechnung von A*10000
ein Überlauf riskiert wird.
Wenn A*10000LL
anstelle von A*10000
in der Formel verwendet wird, wird mit einer gewissen Geschwindigkeit gehandelt, um das Limit auf einen viel größeren Wert zu erhöhen.
Natürlich kann es einen Präzisionsverlust in der Gleitkommazahl geben. Entweder Sie sollten die Festkommazahl als Antwort auf @ 6502 verwenden oder eine Verzerrung zum Ergebnis hinzufügen, um die beabsichtigte Antwort zu erhalten. Sie sollten besser
tun %Vor% Wegen des Genauigkeitsverlustes kann das Ergebnis von (((1 - (double)A/B) / 0.01)) * 100
etwas weniger oder mehr als beabsichtigt sein. Wenn Sie zusätzliche 0.5
hinzufügen, ist es garantiert etwas mehr als beabsichtigt. Wenn Sie nun diesen Wert in eine Ganzzahl umwandeln, erhalten Sie die beabsichtigte Antwort. (Boden- oder Deckenwert, abhängig davon, ob der Bruchteil des Ergebnisses der Gleichung über oder unter 0,5 liegt)
[ Ich habe darauf in einem Kommentar zu der ursprünglichen Frage hingewiesen, aber ich würde es als Antwort veröffentlichen. ]
Das Kernproblem besteht darin, dass die von Ihnen verwendete Ausdrucksform den unvermeidlichen Gleitkommaverlust der Genauigkeit verstärkt, wenn einfache Bruchteile von 10 dargestellt werden.
Dein Ausdruck (mit den momentan entfernten Absätzen, mit der Standard-Präzedenz, um auch einige Parens zu vermeiden)
%Vor%ist eine ziemlich komplizierte Art, das zu repräsentieren, was Sie wollen, obwohl es algebraisch korrekt ist. Unglücklicherweise können Gleitkommazahlen nur Zahlen wie 1/2, 1/4, 1/8 usw., deren Vielfache und deren Summen präzise darstellen. Insbesondere haben weder 9/10 noch 1/10 oder 1/100 genaue Darstellungen.
Der obige Ausdruck führt diese Fehler zweimal ein: zuerst in der Berechnung von A/B
und dann in der Division von 0.01
. Diese zwei ungenauen Werte werden dann geteilt, was den inhärenten Fehler weiter verstärkt.
Der direkteste Weg, um zu schreiben, was Sie meinten (wiederum ohne benötigte Umwandlungen) ist
%Vor%Dies ergibt die richtige Antwort und wesentlich einfacher zu lesen, würde ich vorschlagen, als das Original. Die vollständig korrekte C-Form ist
%Vor%Ich habe das getestet und es funktioniert zuverlässig. Wie andere bereits angemerkt haben, ist es im Allgemeinen besser, mit Double statt Floats zu arbeiten, da sie aufgrund ihrer zusätzlichen Präzision weniger anfällig (aber nicht immun) für diese Art von Schwierigkeit sind.
Tags und Links c++