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

υπολογισμός σε c.. τι κάνω λάθος


karabouzouk...

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

Δημοσ.
>#include<stdio.h>
int main () {
   float y=500,x=0.33439, p;
   
   p=x*y;
   printf("\n\n...... %f\n\n", p);
   return 0;
}

 

Ακόμη κανείς δεν βρήκε τίποτα γι αυτό το θέμα....??

Τρέχοντας απλά το παραπάνω προγραμματάκι που κάνει έναν πολλαπλασιασμό μου βγάζει αποτέλεσμα 167,195007 ενώ το κανονικό αποτέλεσμα είναι 167,195...

Σε εσάς γίνεται έτσι η βγάζει το κανονικό αποτέλεσμα...?

Καμιά πρόταση.. καμιά εξήγηση...?

 

Μαν, δοκίμασε να βάλεις double.

Afaik, η float μπορεί να δείξει μέχρι 6 δεκαδικά ψηφία, αλλά δεν παίρνω και όρκο.

  • Απαντ. 37
  • Δημ.
  • Τελ. απάντηση
Δημοσ.
>#include<stdio.h>
int main () {
   float y=500,x=0.33439, p;
   
   p=x*y;
   printf("\n\n...... %f\n\n", p);
   return 0;
}

 

Ακόμη κανείς δεν βρήκε τίποτα γι αυτό το θέμα....??

Τρέχοντας απλά το παραπάνω προγραμματάκι που κάνει έναν πολλαπλασιασμό μου βγάζει αποτέλεσμα 167,195007 ενώ το κανονικό αποτέλεσμα είναι 167,195...

Σε εσάς γίνεται έτσι η βγάζει το κανονικό αποτέλεσμα...?

Καμιά πρόταση.. καμιά εξήγηση...?

Το πρότυπο C99 καθορίζει ότι εάν δεν υπάρχει διαφορετική οδηγία για το %f, η default τιμή δεκαδικών ψηφίων είναι 6. Το αποτέλεσμα 500·0.33439 δίνει 167.195 τα οποία όμως ο compiler είναι αναγκασμένος λόγω προτύπου και λόγω ορισμού του τύπου του p και του x και του y ως float, να τα γεμίσει έως ότου να συμπληρωθούν 6 δεκαδικά ψηφία. Τα γεμίζει με συγκεκριμένο τρόπο εξ ου και η λάθος τιμή. Ο συγκεκριμένος τρόπος μπορεί να δοθεί εάν μου ζητηθεί. Η χρησιμοποίηση αντί για το %f, του %.3f λύνει το πρόβλημα.

Η χρησιμοποίηση double ή long double για τον ορισμό των x,y,p λύνει το πρόβλημα.

 

Μετά.

Δημοσ.
Να κάνω και εγώ μια ερώτηση ρε παιδιά; Ποστάρω εδώ για να μην ανοίγω άλλο thread άσκοπα, και το ερώτημά μου έχει να κάνει πάλι με floating point calculations.

 

Λοιπόν, έχω γράψει το παρακάτω προγραμματάκι

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

float calc(float n1, float n2);

int main(void)
{
float num1, num2, result;

printf("Enter two floating point numbers (q to quit): ");
while (scanf("%f %f", &num1, &num2) == 2)
{	
	result = calc(num1,num2);
	printf("\nThe result is %f \n", result);
	printf("Enter two floating point numbers (q to quit): ");
	result = 0;
}
return 0;
}

float calc(float n1, float n2)
{	
return (fabs(n1-n2)/(n1*n2)); //επιστρέφει το πηλίκο της απόλυτης τιμή της διαφοράς των δύο αριθμών με το γινόμενο τους
}

 

Γιατί αν δηλώσω τις μεταβλητές ως double αλλά και το return type της συνάρτησης ως double, δίνει άκυρα αποτελέσματα του στυλ:

>
Enter two floating point numbers (q to quit): 2 1
The result is 11298...565.000000

(μην κάνετε σχόλια γιατί έχω βάλει την πράξη σε function, άσκηση είναι...)

 

Εάν τις κάνω float, no problem :/

 

Εκτός από την αλλαγή των float σε double άλλαξε και το scanf από %f σε %lf ώστε οι τιμές να γίνονται parse ως double.

 

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

double calc(double n1, double n2);

int main(void)
{
double num1, num2, result;

printf("Enter two doubleing point numbers (q to quit): ");
while (scanf("%lf %lf", &num1, &num2) == 2)
{
	result = calc(num1,num2);
	printf("\nThe result is %f \n", result);
	printf("Enter two doubleing point numbers (q to quit): ");
	result = 0;
}

getchar();
return 0;
}

double calc(double n1, double n2)
{
return (fabs(n1-n2)/(n1*n2)); //επιστρέφει το πηλίκο της απόλυτης τιμή της διαφοράς των δύο αριθμών με το γινόμενο τους
}

 

 

===============================================================

 

>#include<stdio.h>
int main () {
   float y=500,x=0.33439, p;
   
   p=x*y;
   printf("\n\n...... %f\n\n", p);
   return 0;
}

 

Ακόμη κανείς δεν βρήκε τίποτα γι αυτό το θέμα....??

Τρέχοντας απλά το παραπάνω προγραμματάκι που κάνει έναν πολλαπλασιασμό μου βγάζει αποτέλεσμα 167,195007 ενώ το κανονικό αποτέλεσμα είναι 167,195...

Σε εσάς γίνεται έτσι η βγάζει το κανονικό αποτέλεσμα...?

Καμιά πρόταση.. καμιά εξήγηση...?

 

Όπως εξήγησα ήδη στο πρώτο μου post (http://www.insomnia.gr/forum/showpost.php?p=2605371&postcount=11) είναι θέμα της ακρίβειας που ζητάς από την C. Για παράδειγμα δώσε %.3f και θα έχεις την τιμή που επιθυμείς.

 

>
#include<stdio.h>
int main () {
float y=500,x=0.33439, p;

p=x*y;
printf("\n\n...... %.3f\n\n", p);
getchar();
return 0;
}

Δημοσ.
Το πρότυπο C99 καθορίζει ότι εάν δεν υπάρχει διαφορετική οδηγία για το %f, η default τιμή δεκαδικών ψηφίων είναι 6. Το αποτέλεσμα 500·0.33439 δίνει 167.195 τα οποία όμως ο compiler είναι αναγκασμένος λόγω προτύπου και λόγω ορισμού του τύπου του p και του x και του y ως float, να τα γεμίσει έως ότου να συμπληρωθούν 6 δεκαδικά ψηφία. Τα γεμίζει με συγκεκριμένο τρόπο εξ ου και η λάθος τιμή. Ο συγκεκριμένος τρόπος μπορεί να δοθεί εάν μου ζητηθεί. Η χρησιμοποίηση αντί για το %f, του %.3f λύνει το πρόβλημα.

Η χρησιμοποίηση double ή long double για τον ορισμό των x,y,p λύνει το πρόβλημα.

 

Μετά.

 

Αν δεν σου κάνει κόπο εξήγησε με τι τρόπο γεμίζει τα δεκαδικά μήπως καταλάβω καλύτερα... Με τι τρόπο γίνεται ο πολλαπλασιασμός δηλαδή....

Δημοσ.

@karabouzouk

 

Σωστά σου είπαν για την ακρίβεια, αλλά λάθος να το παίξεις με τα δεκαδικά.

 

Ο λόγος που εμφανίζεται το λάθος είναι γιατί ο foros 0.33439 που βάζεις, αποθηκεύεται σαν 0.3343900144. Κανε άμα θες ένα

>printf("%20.15f",(float)foros)

για

να δεις τι έχει "αποθηκευτεί" μέσα του (το αποθηκευτεί είναι σε εισαγωγικά, διότι είναι define, αλλά πριν την πράξη ή την εκτύπωση ο compiler το αποθηκεύει).

 

Δώσε double σε όλες τις τιμές και κάνε το foros double

>const double foros = 0.33439; 
ή
#define foros  ((double)0.33439)
ή
#define foros  0.33439l

και τα scanf να γίνουν με %lf αντί %f και θα δουλέψουν όλα ρολόι

Δημοσ.

Προσπαθώ να κάνω το απλούστατο του απλούστατου - αρχικοποίηση πίνακα:

 

#include <stdio.h>

#include <stdlib.h>

 

 

main()

{

int j;

float pin[28];

 

for (j=0;j<28;j++);

 

scanf("%f",pin[j]);

 

system ("PAUSE");

}

 

και μόλις βάλω μία τιμή σταματάει.Στο debug μου βγάζει:An access violation ( segmentation fault ) raised in your program.

 

Γνωρίζει κανείς γιατί το κάνει αυτό και πως λύνεται;Ευχαριστώ πολύ!

Δημοσ.

for (j=0;j<28;j++) /* Χωρίς ερωτηματικό στο τέλος */

 

scanf("%f", &pin[j]);

 

 

Ο κώδικας ολοκληρωμένος:

 

>#include <stdio.h>
#include <stdlib.h>

int main(void) {
   int j;
   float pin[28];

   for(j=0;j<28;j++)            /* Χωρίς τον χαρακτήρα ';' στο τέλος */
       scanf("%f", &pin[j]);    /* Πρόσεξε τον χαρακτήρα '&' που προστέθηκε! */

   system("PAUSE");
   return 0;
}

Δημοσ.
@karabouzouk

 

Σωστά σου είπαν για την ακρίβεια, αλλά λάθος να το παίξεις με τα δεκαδικά.

 

Ο λόγος που εμφανίζεται το λάθος είναι γιατί ο foros 0.33439 που βάζεις, αποθηκεύεται σαν 0.3343900144. Κανε άμα θες ένα

>printf("%20.15f",(float)foros)

για

να δεις τι έχει "αποθηκευτεί" μέσα του (το αποθηκευτεί είναι σε εισαγωγικά, διότι είναι define, αλλά πριν την πράξη ή την εκτύπωση ο compiler το αποθηκεύει).

 

Δώσε double σε όλες τις τιμές και κάνε το foros double

>const double foros = 0.33439; 
ή
#define foros  ((double)0.33439)
ή
#define foros  0.33439l

και τα scanf να γίνουν με %lf αντί %f και θα δουλέψουν όλα ρολόι

 

Έχεις δίκιο για το double αλλά έχω κάποιες απορίες...

πρώτον με τι τρόπο ακριβώς αποθηκεύονται πχ τα define και δεν έχω ακριβώς τον αριθμό που αποθηκεύω..?

δεύτερον τι ακριβώς είναι το %lf γιατί δεν το έχω ξαναδεί...

τέλος πόσα δεκαδικά και ακέραια ψηφία έχει ο float, double κλπ...?

και ελπίζω εξηγώντας μου αυτά να καταλάβω και γιατί χρειάζεται να ορίσω τις μεταβλητές double και δεν δουλεύει και με float..

Ευχαριστώ πολύ για το χρόνο σας..!

Δημοσ.

πρώτον με τι τρόπο ακριβώς αποθηκεύονται πχ τα define και δεν έχω ακριβώς τον αριθμό που αποθηκεύω..?

δεύτερον τι ακριβώς είναι το %lf γιατί δεν το έχω ξαναδεί...

τέλος πόσα δεκαδικά και ακέραια ψηφία έχει ο float, double κλπ...?

και ελπίζω εξηγώντας μου αυτά να καταλάβω και γιατί χρειάζεται να ορίσω τις μεταβλητές double και δεν δουλεύει και με float..

Ευχαριστώ πολύ για το χρόνο σας..!

 

τα define δεν αποθηκεύονται, 1000000 define δεν πιάνουν ούτε 1 byte στο exe του προγράμματος σου.

%f,%lf χρειάζονται στην scanf για να ξέρει τι μέγεθος mastissa και exponent να ενημερώσει (απλής ή διπλής ακρίβειας αριθμούς).

Ούτε με double δουλεύει πάντα. Αυτή είναι οι ιδιαιτερότητα των υπολογιστών, έχουν περιορισμούς στην ακρίβεια. π.χ. μια ερώτηση: το 1/3 πόσα δεκαδικά ψηφεία έχει; Μπορούν να αποθηκευτούν σε float ή double; Έστω ότι καταφέρναμε να αποθηκεύσουμε αριθμούς με άπειρα δεκαδικά ψηφία. Πόσο χρόνο θα θέλαμε για να κάνουμε τις πράξεις τέτοιων αριθμών; Στις σχολές πληροφορικής υπάρχει μάθημα αριθμητικής ανάλυσης γι'αυτο το λόγο.

Δημοσ.
τα define δεν αποθηκεύονται, 1000000 define δεν πιάνουν ούτε 1 byte στο exe του προγράμματος σου.

%f,%lf χρειάζονται στην scanf για να ξέρει τι μέγεθος mastissa και exponent να ενημερώσει (απλής ή διπλής ακρίβειας αριθμούς).

Ούτε με double δουλεύει πάντα. Αυτή είναι οι ιδιαιτερότητα των υπολογιστών, έχουν περιορισμούς στην ακρίβεια. π.χ. μια ερώτηση: το 1/3 πόσα δεκαδικά ψηφεία έχει; Μπορούν να αποθηκευτούν σε float ή double; Έστω ότι καταφέρναμε να αποθηκεύσουμε αριθμούς με άπειρα δεκαδικά ψηφία. Πόσο χρόνο θα θέλαμε για να κάνουμε τις πράξεις τέτοιων αριθμών; Στις σχολές πληροφορικής υπάρχει μάθημα αριθμητικής ανάλυσης γι'αυτο το λόγο.

 

Εντάξει ρε συ ξεφεύγεις.....καταννοητό ότι δεν μπορούμε να δουλέψουμε με άπειρα δεκαδικά και δεν υπάρχει λόγος.....στο παράδειγμά μου κάνω έναν απλό πολλαπλασιασμό και βγάζω λάθος αποτέλεσμα... με double ok λύνεται το πρόβλημα.... προβλημά μου είναι να καταλάβω γιατί ενώ βάζω τη μεταβλητή φόρος 0,33439 "αποθηκεύεται" ή τέλος πάντων όταν την κάνω printf εμφανίζεται σαν 0.3343900144 όπως είπες και σύ...

Δημοσ.

floating point representation

ή καλύτερα εδώ

 

 

>#include <stdio.h>

//ο παρακάτω κώδικας λειτουργεί για sizeof(float)==sizeof(long)==4
//δεν φτιάχτηκε για portability αλλα για παραδειγμα "κωδικοποίησης" float

void p(float k){
union {
	float f;
	unsigned long l;
} x;
size_t i;
x.f = k;
printf("%35.27f\t",k);
for(i=0;i<32;i++){
	putchar((x.l & 0x80000000lu) ? '1':'0');
	x.l <<= 1;
}
printf("\n");
}

int main(void){
p(0.33439);
return 0;	
}

 

 

1bit=sign, 8bit=exponent, 23bit=value

 

να ο αριθμός 0.33439 όταν αποθηκευτεί σε float 4 bytes (single presition):

0.334390014410018921000000000

και η δυαδική του αναπαράσταση (τα 32bit) σύμφωνα με το προγραμματάκι που παρέθεσα είναι:

0 01111101 01010110011010100101011

 

απο τα οποία:

0=sign (θετικός)

01111101=125 (στο δεκαδικό) σημαίνει 125-127 = -2 εκθέτης (με βάση το 2)

01010110011010100101011

η mantissa έχει το κρυφό ψηφείο 1 στην αρχή αρα είναι

101010110011010100101011

 

Να και τα βάρη των ψηφείων:

bit 23 = 1

bit 22 = 0.5

bit 21 = 0.25

bit 20 = 0.125

bit 19 = 0.0625

...

δηλαδή το most significant bit είναι το 1 και καθως πηγαίνουμε προς τα πίσω διαιρούμε με το 2. Αν τα βάλεις σε κανένα excel/scalc θα βρείς τον πλήρη πίνακα

>
Θέση bit	βάρος θέσης	bit αριθμού μας	βάρος αριθμού μας
23	1,00000000000000000000	1	1,00000000000000000000
22	0,50000000000000000000	0	0,00000000000000000000
21	0,25000000000000000000	1	0,25000000000000000000
20	0,12500000000000000000	0	0,00000000000000000000
19	0,06250000000000000000	1	0,06250000000000000000
18	0,03125000000000000000	0	0,00000000000000000000
17	0,01562500000000000000	1	0,01562500000000000000
16	0,00781250000000000000	1	0,00781250000000000000
15	0,00390625000000000000	0	0,00000000000000000000
14	0,00195312500000000000	0	0,00000000000000000000
13	0,00097656250000000000	1	0,00097656250000000000
12	0,00048828125000000000	1	0,00048828125000000000
11	0,00024414062500000000	0	0,00000000000000000000
10	0,00012207031250000000	1	0,00012207031250000000
9	0,00006103515625000000	0	0,00000000000000000000
8	0,00003051757812500000	1	0,00003051757812500000
7	0,00001525878906250000	0	0,00000000000000000000
6	0,00000762939453125000	0	0,00000000000000000000
5	0,00000381469726562500	1	0,00000381469726562500
4	0,00000190734863281250	0	0,00000000000000000000
3	0,00000095367431640625	1	0,00000095367431640625
2	0,00000047683715820313	0	0,00000000000000000000
1	0,00000023841857910156	1	0,00000023841857910156
0	0,00000011920928955078	1	0,00000011920928955078
	Σύνολο	1,33756005764008000000

 

(μεχρι 20 ψηφία ακρίβεια έχει το oo calc που δοκίμασα)

 

η πρώτη στήλη είναι η θέση του bit, η δεύτερη η σημασία της (βάρος), η τρίτη είναι η τιμή των βιτ του αριθμού σου, η τέταρτη είναι το γινόμενο της 2ής με την 3η.

 

Το άθροισμα είναι 1,3375... και αν το πολλαπλασιασουμε με το 2^-2, δινει

0,33439001441001900000 [voila]

 

αν βάλεις στο excel/scalc τους πίνακες που σου έδωσα και στο bit 0 βάλεις 0 αντί για 1 (που έχει), βρίσκεις την αμέσως μικρότεερη δυνατή τιμή που μπορεί να αποθηκευτεί και είναι η

0,33438998460769700000

 

δηλαδη μετά το 0,33438998460769700000

υπάρχει το 0,33439001441001900000

Δημοσ.
προβλημά μου είναι να καταλάβω γιατί ενώ βάζω τη μεταβλητή φόρος 0,33439 "αποθηκεύεται" ή τέλος πάντων όταν την κάνω printf εμφανίζεται σαν 0.3343900144 όπως είπες και σύ...

 

τελικά το κατάλαβες;

  • 4 εβδομάδες αργότερα...
Δημοσ.

Απλούστατο θέμα που δε μπορώ να καταλάβω γιατί δε λειτουργεί:

 

max=ar[0];

 

for (j=1;j<NUMBERS;j++)

if (ar[j]>max)

max=ar[j];

 

printf("MAX:%d\n",max);

 

Το γράφω ισοδύναμα:

 

max=ar[0];

 

for (j=1;j<NUMBERS;j++)

total=ar[j]>max?ar[j]:max;

 

printf("MAX:%d\n",total);

 

Δεν έχω τα ίδια αποτελέσματα.Μάλλον δεν είναι και τόσο ισοδύναμες οι μορφές.Κάποια ιδέα παρακαλώ πολύ.

Δημοσ.
Απλούστατο θέμα που δε μπορώ να καταλάβω γιατί δε λειτουργεί:

 

max=ar[0];

 

for (j=1;j<NUMBERS;j++)

if (ar[j]>max)

max=ar[j];

 

printf("MAX:%d\n",max);

 

Το γράφω ισοδύναμα:

 

max=ar[0];

 

for (j=1;j<NUMBERS;j++)

total=ar[j]>max?ar[j]:max;

 

printf("MAX:%d\n",total);

 

Δεν έχω τα ίδια αποτελέσματα.Μάλλον δεν είναι και τόσο ισοδύναμες οι μορφές.Κάποια ιδέα παρακαλώ πολύ.

 

Στην δευτερη περίπτωση αν NUMBERS==0, το total δεν θα πάρει τιμή.

Στην δευτερη περίπτωση, το max παραμένει ar[0] (δεν το ενημερωνεις).

Αρχειοθετημένο

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

  • Δημιουργία νέου...