Genaue Prozentangabe in C ++

8

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?

    
DragonSlayer 19.07.2014, 05:22
quelle

4 Antworten

10

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.

    
6502 19.07.2014, 05:25
quelle
2

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)

    
Mohit Jain 19.07.2014 05:38
quelle
0

Ich habe es versucht

%Vor%

zeigt 1000

an

Ich vermute einen Präzisionsverlust beim automatischen Casting, um das Root-Problem für Ihren Code zu int.

    
Vivek V K 19.07.2014 05:41
quelle
0

[ 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.

    
Dale Hagglund 19.07.2014 18:36
quelle

Tags und Links