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

Γενικό thread αποριών για τη C#.


Alithinos

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

Εδώ και καιρό μετέτρεπα μια μεταβλητή ενός τύπου σε άλλου τύπου, με τις μεθόδους του .net, πχ

 

Convert.ToInt32();

 

Πριν κάτι μέρες όμως έμαθα πως γίνεται και με το casting, το οποίο το κάνεις με τον εξής τύπο για παράδειγμα:

double d = 12.5;
int i;

i = (int) d;
αντί του να γράψεις
double d = 12.5;
int i;

i = Convert.ToInt32(d);
Ωστόσο δεν είδα να αναφέρει τις διαφορές μεταξύ αυτών των δύο τρόπων.

Δηλαδή, που συμφέρει να προτιμώ τον ένα τρόπο σε σχέση με τον άλλο ; Είναι ένας από τους δύο τρόπους πιο γρήγορος από τον άλλο ; Η συνήθεια μου είναι να μετατρέπω με τις μεθόδους του .NET, αξίζει να ξεσυνηθίσω ?

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

  • Απαντ. 505
  • Δημ.
  • Τελ. απάντηση

Συχνή συμμετοχή στο θέμα

Συχνή συμμετοχή στο θέμα

Δημοσιευμένες Εικόνες

Καταρχας δεν επιστρέφουν ιδια τιμή.

double d = 1.5;
int a = (int)d;   //a=1
int b = Convert.ToInt32(d);  //b=2

Αυτός ειναι ο κώδικας της Convert (από το ILSpy)

public static int ToInt32(double value)
{
	if (value >= 0.0)
	{
		if (value < 2147483647.5)
		{
			int num = (int)value;
			double num2 = value - (double)num;
			if (num2 > 0.5 || (num2 == 0.5 && (num & 1) != 0))
			{
				num++;
			}
			return num;
		}
	}
	else
	{
		if (value >= -2147483648.5)
		{
			int num3 = (int)value;
			double num4 = value - (double)num3;
			if (num4 < -0.5 || (num4 == -0.5 && (num3 & 1) != 0))
			{
				num3--;
			}
			return num3;
		}
	}
	throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}
  • Like 2
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

 

Καταρχας δεν επιστρέφουν ιδια τιμή.

double d = 1.5;
int a = (int)d;   //a=1
int b = Convert.ToInt32(d);  //b=2

Αυτός ειναι ο κώδικας της Convert (από το ILSpy)

public static int ToInt32(double value)
{
	if (value >= 0.0)
	{
		if (value < 2147483647.5)
		{
			int num = (int)value;
			double num2 = value - (double)num;
			if (num2 > 0.5 || (num2 == 0.5 && (num & 1) != 0))
			{
				num++;
			}
			return num;
		}
	}
	else
	{
		if (value >= -2147483648.5)
		{
			int num3 = (int)value;
			double num4 = value - (double)num3;
			if (num4 < -0.5 || (num4 == -0.5 && (num3 & 1) != 0))
			{
				num3--;
			}
			return num3;
		}
	}
	throw new OverflowException(Environment.GetResourceString("Overflow_Int32"));
}

 

:blink:

 

Όντως με το 1.5 δεν επιστρέφουν ίδια τιμή! Έτυχε και με τους αριθμούς που δοκίμασα χθες, όπως το 12.5 και έβγαλε την ίδια.

 

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Επισκέπτης

Η Convert.ToInt32 μπορεί να πάρει ως παράμετρο ακόμα και string. Το (int)something προϋποθέτει ότι το something θα είναι αριθμός.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το θέμα είναι πολύ μεγάλο για να απαντηθεί σε λογική έκταση. Πολύ συνοπτικά, τα casts κάνουν ένα συγκεκριμένο πράγμα γνωστό at compile time δεδομένου του τύπου του τελεστέου και του cast. Το Convert παίρνει όχι ακόμα και string αλλά ακόμα και οποιοδήποτε object σαν παράμετρο, το τι θα κάνει μ' αυτό άβυσσος η ψυχή του υπολογιστή, θα αποφασιστεί at runtime.

 

Επίσης, εδώ περιοριζόμαστε στην υποπερίπτωση θέλω έναν numeric primitive να τον κάνω int. Και το cast και το Convert κάνουν επίσης κι άλλα πράγματα εκτός από αυτό (όχι τα ίδια).

 

http://stackoverflow.com/questions/15394032/difference-between-casting-and-using-the-convert-to-method

  • Like 4
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Βασικά αυτό που λέει ο defacer.

 

Απλά παρένθεση, @albNik δε χρειάζεται να παιδεύεσαι με il-ματζούνια για να δεις τον κώδικα του .net framework (του μεγαλύτερου μέρους νομίζω). 

 

Είναι ανοιχτός πια

 

http://referencesource.microsoft.com/#mscorlib/system/convert.cs,10cd63a0dc4a7c4c

  • Like 3
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Προσωπικά βρίσκω ακόμα ευκολότερο το dotPeek για τέτοιες γρηγοράντζες

 

https://www.jetbrains.com/decompiler/

 

Ανοίγεις το πρόγραμμα, Ctrl+T "Go to everything", γράφεις Convert.ToInt32, επιλέγεις το κατάλληλο overload από τη λίστα κατεβάζει μόνο του ο,τι χρειάζεται αν δεν το έχεις ήδη και....

 

qeLm2Ti.png

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Βασικά αυτό που λέει ο defacer.

 

Απλά παρένθεση, @albNik δε χρειάζεται να παιδεύεσαι με il-ματζούνια για να δεις τον κώδικα του .net framework (του μεγαλύτερου μέρους νομίζω). 

 

Είναι ανοιχτός πια

 

http://referencesource.microsoft.com/#mscorlib/system/convert.cs,10cd63a0dc4a7c4c

lol ποτε το ανοιξε;

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

lol ποτε το ανοιξε;

 

Δεν είμαι σίγουρος. Πάντως τον κώδικα του .νετ τον έβρισκα την εποχή που ασχολιόμουν ακόμα με αυτό (c# 4.0). 

Απλά τότε νομίζω οτι απλά μπορούσες να τον δεις.

 

Εδώ και καιρό ωστόσο έχει γίνει κανονικά opensource - github φάση το μεγαλύτερο μέρος του αν όχι όλο.

 

http://dotnet.github.io/

 

https://github.com/Microsoft/dotnet

 

Θα εκπλαγείς απο το πόσα πράγματα έχει κάνει κανονικά open source. 

 

Εδώ που τα λέμε άργησε. Έπρεπε να το είχε κάνει εδώ και πάρα πολύ καιρό.

 

EDIT:

 

Και εδώ να δεις ομορφιές CI δημόσιο φυσικά με jenkins παρακαλώ:

 

http://dotnet-ci.cloudapp.net/

  • Like 1
Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Για να καταλάβω καλύτερα το casting είπα να βρω μια άσκηση με αυτό.

Και βρήκα την εξής: 

 

Να υπολογίσω το ποσό κάθε δόσης σε ένα δάνειο.

Το αρχικό κεφάλαιο είναι 10000$, με 12 δόσεις το χρόνο, για 5 χρόνια, και το ετήσιο επιτόκιο 0.075.

Το αποτέλεσμα πρέπει να είναι 200.38

 

Η άσκηση δίνει ένα μαθηματικό τύπο:

 

Δόση = [Επιτόκιο * (Κεφάλαιο / ΠληρωμέςΑνάΈτος) / 1 - ((Επιτόκιο / ΠληρωμέςΑνάΈτος) + 1) -ΠληρωμέςΑνάΈτος * ΑριθμόςΕτών]

 

Έγραψα τούτο: (βάζω τις τιμές με user input)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Askisi
{
    class Program
    {
        static void Main(string[] args)
        {
            decimal Kefalaio;
            decimal epitokio;
            decimal doseisAnaEtos;
            decimal arithmosEton;
            decimal posoDosis;
            decimal diaireteos, diairetis;
            decimal b1, b2;
            double b, e;

            Console.WriteLine("Δώσε το συνολικό ποσό του κεφαλαίου: ");
            Kefalaio = Convert.ToDecimal(Console.ReadLine());

            Console.WriteLine("Δώσε τον αριθμό ετών που θα διαρκέσει η αποπληρωμή: ");
            arithmosEton = Convert.ToDecimal(Console.ReadLine());

            Console.WriteLine("Πόσες δόσεις θα δίνεις κάθε έτος: ");
            doseisAnaEtos = Convert.ToDecimal(Console.ReadLine());

            Console.WriteLine("Δώσε το ποσό του ετήσιου επιτόκιου");
            epitokio = Convert.ToDecimal(Console.ReadLine());

           diaireteos = epitokio * (Kefalaio / doseisAnaEtos); 

             b1 =  1 - ((epitokio / doseisAnaEtos) + 1);
             b2 = -doseisAnaEtos * arithmosEton;

            b = (double)(b1);
            e = (double)(b2);

            diairetis = (decimal) Math.Pow(b, e);
            posoDosis = diaireteos / diairetis;

      
            Console.WriteLine("Το ποσό της κάθε δόσης θα είναι: {0}",posoDosis);


            Console.ReadLine();




        }
    }
}

Το Visual Studio δεν διαμαρτύρεται, αλλά το πρόγραμμα μου πετά runtime error OverflowException, και ελέγχω ότι η μεταβλητή diairetis μηδενίζεται!

 

Έχει κάποιο λάθος ο τύπος της άσκησης ή ποιο είναι το δικό μου λάθος ?

Γιατί ο διαιρέτης μου γίνεται 0 ?

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

To

  b1 = 1 - ((epitokio / doseisAnaEtos) + 1); 

τι φαση; 

 

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

 

Ο διαιρετέος της είναι το

[Επιτόκιο * (Κεφάλαιο / ΠληρωμέςΑνάΈτος)

 

και διαιρέτης το

 

 

 

1 - ((Επιτόκιο / ΠληρωμέςΑνάΈτος) + 1) -ΠληρωμέςΑνάΈτος * ΑριθμόςΕτών

 

 

O διαιρέτης είναι μακρύς, και έτσι αποφάσισα να τον σπάσω σε δύο μικρότερα κομμάτια, ένα κομμάτι τη βάση και το άλλο η δύναμη.

 

Έτσι έχουμε τη βάση η οποία είναι το

 

1 - ((Επιτόκιο / ΠληρωμέςΑνάΈτος) + 1) 

 

 

και τη δύναμη

 

-ΠληρωμέςΑνάΈτος * ΑριθμόςΕτών

 

 

Η μεταβλητή b1 αντιστοιχεί στη βάση, την οποία θέλω να υψώσω στη δύναμη b2.

Επειδή όμως b1 και b2 είναι και τα δύο decimal, και η Math.Pow() δεν δέχεται decimal, μετατρέπω τις b1 και b2 σε b και e τύπου double αντίστοιχα, ώστε να τις χρησιμοποιήσει η Math.Pow, για να μεταφέρω τον τύπο.

Στη συνέχεια κάνω τη διαίρεση, αλλά σε αυτό το βήμα πετάει runtime error, γιατί πλέον ο διαιρέτης έχει πάρει τη τιμή 0.

Θες να σου λύσουμε και την άσκηση;

 

Όχι δεν θέλω το κώδικα της άσκησης λυμένο. Δε μου την έχει βάλει κάποιος να πρέπει να του τη δείξω, εγώ την έβαλα στον εαυτό μου.

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

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Το θέμα ξέρεις ποιο είναι ?

Πως άμα αγνοήσω τον παραπάνω τύπο που μου δίνει η άσκηση, και αποφασίσω να το λύσω το πρόβλημα με αλγόριθμο δική μου επινόησης, γράφω το παρακάτω: 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Askisi
{
    class Program
    {
        static void Main(string[] args)
        {
            decimal Kefalaio; // Αρχικό ποσό δανείου, 10000.00
            decimal epitokio; // Επιτόκιο, 0.075
            decimal doseisAnaEtos; // 12 δόσεις το χρόνο
            decimal arithmosEton; // 5 χρόνια
            decimal posoDosisXorisEpitokio; // το ποσό μηνιαίας δόσης χωρίς το επιτόκιο.
            decimal arithmosdoseon; // ο συνολικός αριθμός δόσεων, 60.
            decimal neoposo; // χρησιμοποιείται παρακάτω
            decimal posodosisMeEpitokio; // το τελικό ποσό της κάθε δόσης, μαζί με επιτόκιο.

            Console.WriteLine("Δώσε το συνολικό ποσό του κεφαλαίου: ");
            Kefalaio = Convert.ToDecimal(Console.ReadLine());

            Console.WriteLine("Δώσε τον αριθμό ετών που θα διαρκέσει η αποπληρωμή: ");
            arithmosEton = Convert.ToDecimal(Console.ReadLine());

            Console.WriteLine("Πόσες δόσεις θα δίνεις κάθε έτος: ");
            doseisAnaEtos = Convert.ToDecimal(Console.ReadLine());

            Console.WriteLine("Δώσε το ποσό του ετήσιου επιτόκιου");
            epitokio = Convert.ToDecimal(Console.ReadLine());

            arithmosdoseon = doseisAnaEtos * arithmosEton;
            posoDosisXorisEpitokio = Kefalaio / arithmosdoseon;

            posodosisMeEpitokio = posoDosisXorisEpitokio + epitokio;
            neoposo = posodosisMeEpitokio;

            for (int i = 0; i < arithmosEton; i++)
            {
                neoposo = posodosisMeEpitokio + epitokio;
            }
            Console.WriteLine("Το ποσό της κάθε δόσης θα είναι: {0:N}", neoposo);


            Console.ReadLine();




        }
    }
}

Το οποίο φυσικά όμως δεν δίνει 200.38 τη κάθε δόση, αλλά 166.67.

 

Και έψαξα στο google να βρω online υπολογιστές δανείων, και βρήκα 4-5.

Και βάζοντας τα παραπάνω στοιχεία, δηλαδή 10.000 κεφάλαιο, 60 δόσεις (12 επί 5 χρόνια) με επιτόκιο 0.075, μου βγάζουν σε άλλα sites 166, και άλλα 167. :huh: (μάλλον οι online μετατροπείς χρησιμοποιούν ints και άλλος κόβει ενώ άλλος στρογγυλεύει τα σεντς). Και ΟΧΙ 200.38!!!!

 

Άρα ? Που είναι το λάθος ?

Με το δικό μου αλγόριθμο αδιαφορώντας για τον τύπο του βιβλίου δεν έλυσα το πρόβλημα ?

Αν όχι, τότε γιατί και οι online μετατροπείς βγάζουν τα ίδια αποτελέσματα, και αυτοί όλοι λάθος κάνουν ?

Αν ναι, τότε τι στο καλό μου λέει ο τύπος του βιβλίου, και που βγάζει το 200.38 ως λύση η άσκηση ?

 

Έχει καεί το κεφάλι μου σήμερα!  :mad:  :wacko:

 

υ.γ. θα μου πεις βέβαια, πως με το τρόπο τον δικό μου, δεν χρησιμοποίησα καθόλου το casting, αλλά %#σε το το casting! Παιδεύομαι να βρω τόσες ώρες γιατί δε βγαίνει η άσκηση και μου βγάζει το 166.67 αντί για 200.38 ακολουθώντας το δικό μου τρόπο, και ίσα που παν 10-15 λεπτά που είπα να κοιτάξω για υλοποιήσεις άλλων προγραμμάτων που να κάνουν το ίδιο πράγμα να ελέγξω τι θα δώσουν. Και μετά από τόσες ώρες ανακάλυψα ότι βγάζουν αυτό που έβγαζα και εγώ με τον 'τρόπο μου' εδώ και τόσες ώρες και το θεωρούσα λάθος! Τα νεύρα μου.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

Στην εισαγωγή γραμμής τα δεκαδικά τα βάζεις με τελεία ή με κόμμα; Το Convert.ToDecimal(Console.ReadLine()) δουλεύει με ότι να είναι;

Γιατί ένας αριθμός 0,0075 θα βγει 0 αν περιμένει τελεία για δεκαδικό.

Συνδέστε για να σχολιάσετε
Κοινοποίηση σε άλλες σελίδες

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

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

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

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

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

Σύνδεση

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

Συνδεθείτε τώρα

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