Προς το περιεχόμενο

Προτεινόμενες αναρτήσεις

  • Moderators
Δημοσ.

Μπορείς να το πολλαπλασιάσεις με 10x, όπου x το πλήθος των ψηφίων που σε ενδιαφέρει, μετά να το κάνεις int και μετά πάλι float και επί 10-x.

  • Like 1
Δημοσ.

Ποιος ο λόγος να το βγάλεις; Στους υπολογισμούς που κανεις φαντάζομαι δεν έχει ιδιαίτερη σημασία, και όταν είναι να το τυπώσεις καπου συνήθως μπορεις να ορίσεις πόσα δεκαδικά σε ενδιαφέρουν(πχ στη printf).

Δημοσ.

Ποιος ο λόγος να το βγάλεις; Στους υπολογισμούς που κανεις φαντάζομαι δεν έχει ιδιαίτερη σημασία, και όταν είναι να το τυπώσεις καπου συνήθως μπορεις να ορίσεις πόσα δεκαδικά σε ενδιαφέρουν(πχ στη printf).

Ελα ντε,.. Θα φτάνει η ωρα.

Βασικα ειναι πιο περιπλοκο το round που θελω.

Δημοσ.

1) Μη χρησιμοποιείς float. Απλά δε μπορεί να γίνει σωστή αναπαράσταση.

 

2) Αν θες να κρατήσεις συγκεκριμένο αριθμό δεκαδικών θα μπορούσες να χρησιμοποιήσεις

την ιδέα του bnvdarklord αλλά με συνδυασμό sprintf-sscanf και format identifier %g, οποίος,

αν πας να κόψεις κάποια ψηφία από το δεκαδικό κομμάτι, στρογγυλοποιεί. Κάτι τέτοιο:

sprintf(reg, float_format, lbfl);sscanf(reg, "%lf", &lbfl);

Με ζωντανό παράδειγμα.

Δημοσ.

Γενικά μπορείς να κόψεις όσα ψηφία θέλεις με τους τρόπους που προτάθηκαν. Σε κάποιες τιμές όμως δεν μπορείς να γλυτώσεις τα σκουπίδια λόγω του τρόπου αναπαράστασης.

 

#include <stdio.h>
#include <math.h>

int main(void)
{
	float lblf = 0.150000006;

	printf("%.12f\n", lblf);
	printf("%.12f\n", roundf(lblf * 100.f));
	printf("%.12f\n", roundf(lblf * 100.f) / 100.f);
	printf("%.12f\n", round(lblf * 100.f) / 100.f);

	return 0;
}
Έξοδος:
0.150000005960
15.000000000000
0.150000005960
0.150000000000
Όπως βλέπουμε στην 2η γραμμή, το round παίζει κανονικά και βγάζει 15 αλλά μετά την διαίρεση ερχόμαστε ξανά στην αρχική κατάσταση επειδή η συγκεκριμένη τιμή δεν μπορεί να αναπαρασταθεί σωστά.

 

Στην 4η γραμμή βλέπουμε πως αν χρησιμοποιήσουμε double, τότε παίρνουμε το σωστό αποτέλεσμα λόγω μεγαλύτερης ακρίβειας.

 

Αν χρησιμοποιήσουμε ως αρχική τιμή το 0.160000006 που είναι πολύ καλύτερη τιμή βλέπουμε πως και πάλι σε float έχουμε πρόβλημα μετά τα 6-7 ψηφία.

0.160000011325
16.000000000000
0.159999996424
0.160000000000
Δυστυχώς η γενική σύσταση για FP είναι "μην χρησιμοποιείς ποτέ float" γιατί ο float έχει σκατά ακρίβεια.
Δημοσ.

Γενικά μπορείς να κόψεις όσα ψηφία θέλεις με τους τρόπους που προτάθηκαν. Σε κάποιες τιμές όμως δεν μπορείς να γλυτώσεις τα σκουπίδια λόγω του τρόπου αναπαράστασης.

 

...

Και αυτό φαίνεται ακόμη καλύτερα από εδώ (που λογικά ήθελε να αναπαραστήσει το 0.15):

float lbfl = 0.15f;
printf("lbfl = %.15f\n", lbfl);

Εδώ για αποτελέσματα.

  • Like 1
Δημοσ.

Εχω αυτο
ys3UQpR.png

Η αριθμοι δειχνουν σωστα το transformed space.
Αυτο που θελω ειναι να κανω round το inital y ετσι ωστε να βγαινουν πιο "ωραιοι" οι αριθμοι.

Να αυτο που κανω τωρα

	TextFormatProperties prps;
	this->pTextFormat->GetProperties(prps);

	float maxLabels = (this->rcAxis.top - this->rcAxis.bottom) / (prps.fontSize * 1.2f);
	float Start = (this->rcAxis.bottom - this->transformation.ty) / this->transformation.sy;
	float End = (this->rcAxis.top - this->transformation.ty) / this->transformation.sy;
	float Step = (End - Start) / maxLabels;

	//rounding
	float base = 1.f / Start;
	float test = Start * base;

#if 0
	Start = std::floorf(Start * 100.f) / 100.f;
	End = std::floorf(End * 100.f) / 100.f;
	Step = std::floorf(Step * 100.f) / 100.f;
#endif // 0

	
	//-test

	for (float i = Start; i < End; i += Step)
	{
		std::wstringstream ss;
		ss << std::fixed << std::setprecision(5) << i;
		pPlatform->DrawText(makepoint(left, i * transformation.sy + transformation.ty), ss.str().c_str());
	}

ουσιαστικα κανω invert transform των screen coords ωστε να βρω τι βλεπω σε space coords. Αυτο ομως μου δινει ως πρωτο space coord το 8.177etc. Εγω αυτο θελω να το κανω 8. Θα μου πεις οκ, βαλε ενα floor round whateva, ομως και αυτο δεν κανει επειδη δεν υπαρχουν const. Θα δουλευει στο διαστιμα 8-10 ξερω γω, αλλα δεν θα δουλευει σε 0.8 - 1.0

Δημοσ.
...

Θες να φτιάξεις μία έξυπνη round η οποία αποφασίζει από μόνη της

σε ποιό σημείο θα κάνει round;

Αυτό θα μπορούσες να το κάνεις με strings και parsing.

 

Διαφορετικά, αν ξέρεις και θες να βάζεις εσύ κάθε φορά σε ποιό δεκαδικό

θες στρογγυλοποίηση τότε ρίξε μία ματιά εδώ. Εμένα με έκραξαν για αυτή

τη συνάρτηση λόγω περιορισμένης ακρίβειας, αλλά τί να κάνουμε. Αν έχετε

να προτείνετε κάτι καλύτερο, καλόδεχούμενο.

Πάντως για την περίπτωσή σου δε θα έχεις θέμα.

 

Εδώ θα βρεις και περισσότερα παραδειγματάκια στον κώδικα που σου έδωσα.

long double round_f(long double number, int decimal_places)
{
	assert(decimal_places > 0);
	
	double power = pow(10, decimal_places-1);
	number *= power;
	
	return (number >= 0) ? ((long long)(number + 0.5))/power : ((long long)(number - 0.5))/power;
}
Δημοσ.
Τελικα παραηταν πολυπλοκο

 

 TextFormatProperties prps;
this->pTextFormat->GetProperties(prps);
 
float maxLabels = (this->rcAxis.top - this->rcAxis.bottom) / (prps.fontSize * 1.2f);
float start = (this->rcAxis.bottom - this->transformation.ty) / this->transformation.sy;
float end = (this->rcAxis.top - this->transformation.ty) / this->transformation.sy;
float step = (end - start) / maxLabels;
 
float magPow = std::powf(10.f, std::floorf(std::log10f(step)));
float magMsg = roundf(step / magPow + 0.5);
step = magMsg * magPow;
start = step * std::ceilf(start / step);
end = step * std::floorf(end / step);
 
 
 
for (float i = start; i < end; i += step)
{
std::wstringstream ss;
ss << std::fixed << std::setprecision(5) << i;
pPlatform->DrawText(makepoint(this->rcLabel.left + this->axisSize, i * transformation.sy + transformation.ty), ss.str().c_str());
}
 

Δημιουργήστε ένα λογαριασμό ή συνδεθείτε για να σχολιάσετε

Πρέπει να είστε μέλος για να αφήσετε σχόλιο

Δημιουργία λογαριασμού

Εγγραφείτε με νέο λογαριασμό στην κοινότητα μας. Είναι πανεύκολο!

Δημιουργία νέου λογαριασμού

Σύνδεση

Έχετε ήδη λογαριασμό; Συνδεθείτε εδώ.

Συνδεθείτε τώρα
  • Δημιουργία νέου...