C#: de ce 7 / 2 nu produce 3.5
Înțelege de ce 7 / 2 produce 3 în C# și de ce atribuirea la double nu repară rezultatul. Compară conversia înainte și după împărțire, cu exemple.
În acest material
Ai declarat rezultatul ca double, dar împărțirea a două numere continuă să piardă fracția. Cauza este ordinea evaluării: tipul variabilei în care ajunge rezultatul nu schimbă retroactiv operația deja făcută. Pentru a înțelege problema trebuie privite tipurile operanzilor din expresie.
C# folosește împărțire întreagă când ambii operanzi sunt întregi. Rezultatul elimină partea fracționară spre zero. Pentru operanzi pozitivi aceasta seamănă cu rotunjirea în jos, dar diferența devine vizibilă la numere negative.
Un exemplu care arată problema
Expresia double result = 7 / 2; calculează mai întâi 7/2 ca int și obține 3. Apoi convertește 3 în double, rezultând 3.0. În schimb, double result = 7 / 2.0; folosește un operand double și produce 3.5. Pentru −7 și 2, împărțirea întreagă produce −3, nu −4. Conversia nu poate recupera o fracție care nu mai există în rezultatul intermediar.
Împărțirea întreagă produce 3; conversia ulterioară păstrează 3.0, iar un operand double permite 3.5.Mărește schema ↗
De unde vine diferența
Operatorul / este ales în funcție de tipurile expresiilor din stânga și dreapta sa. O conversie pusă în jurul întregului rezultat, ca (double)(a / b), vine prea târziu. Conversia unui operand, ca (double)a / b, schimbă tipul operației înainte de efectuarea ei. Într-o medie calculată din întregi, aceeași problemă apare la sum / count, chiar dacă variabila mediei este double.
Corecția și limitele ei
Programul de verificare citește a și b pe linii separate, cu valori între −1000 și 1000 și b diferit de zero. Afișează câtul întreg și apoi câtul calculat cu un operand double, cu trei zecimale și punct separator. Limitele evită cazuri de depășire a câtului int. Pentru intrare invalidă afișează INVALID. Nu schimba toate împărțirile în double fără să verifici cerința: extragerea cifrelor sau numărul grupurilor complete pot cere tocmai împărțirea întreagă.
Program de verificare
using System;
using System.Globalization;
class Program
{
static void Main()
{
if (!int.TryParse(Console.ReadLine(), out int a) || !int.TryParse(Console.ReadLine(), out int b) ||
a < -1000 || a > 1000 || b < -1000 || b > 1000 || b == 0)
{ Console.WriteLine("INVALID"); return; }
Console.WriteLine(a / b);
Console.WriteLine(((double)a / b).ToString("F3", CultureInfo.InvariantCulture));
}
}
Cum verifici rezultatul
Verifică 7 și 2, dar și −7 și 2: al doilea caz arată sensul eliminării fracției. Verifică 8 și 2, unde ambele variante reprezintă exact patru, și 1 cu 4, unde diferența este zero față de 0.250. Include numitorul zero ca intrare respinsă. Un test numai cu împărțiri exacte poate ascunde complet greșeala. Cele trei zecimale sunt o regulă de afișare; ele nu înseamnă că double ar reprezenta exact orice raport matematic.
Continuă studiul
Recapitulează Variabile și tipuri în C#: int, double și bool. Recapitulează Citirea datelor în C# cu Console.ReadLine și TryParse. Recapitulează Metode în C#: parametri și valori returnate.
Referință: documentația Microsoft.
Întrebări frecvente
De ce double result = 7 / 2 produce 3?
Pentru că împărțirea dintre cei doi întregi se efectuează înainte de conversia rezultatului în double.
Unde trebuie pusă conversia pentru fracție?
Pe cel puțin un operand înainte de împărțire, de exemplu (double)a / b, nu în jurul rezultatului a / b.
Împărțirea întreagă rotunjește mereu în jos?
Nu. Elimină fracția spre zero. Pentru −7/2 rezultatul este −3, în timp ce rotunjirea matematică în jos ar produce −4.