Forumdelen sponsras av

Trädvy Permalänk
Medlem
Registrerad
Aug 2015

C++ plats på variabel

Hej.

Jag håller på med en skoluppgift i c++.

Där vill dom att jag skall skriva ett program som avrundar ett decimaltal till heltal, vilket jag har kommit på hur jag skall göra.

Men min fundering är varför det inte fungerar med att ha "int heltal = decimal;" under "float decimal;" för ligger den där uppe blir "Avrundat blir talet lika med 0.

Här kommer koden jag har fått att fungera. (Lägger till en kommentar där jag inte förstår varför inte "int heltal = decimal;" fungerar.

#include <iostream>

using namespace std;

int main()
{

float decimal;

// Här skulle jag spontant vilja ha int heltal = decimal;

cout << "Ange ett decimaltal du vill avrunda: ";
cin >> decimal;
int heltal = decimal;
cout << "Decimaltalet: " << decimal << " Avrundat blir talet: " << heltal;
return 0;
}

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Jan 2007

Du behöver i sådana fall casta om den till rätt typ.

Testa
int heltal = (int)decimal

Däremot blir det inte avrundat korrekt. Den kommer alltid avrunda nedåt.

Core i7 7700K | Titan X (Pascal) | MSI 270I Gaming Pro Carbon | 32 GiB Corsair Vengeance LPX @3000MHz | Samsung 960 EVO 1TB

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Sep 2012

Om man bara tar heltal = decimaltal brukar den helt sonika kasta decimalerna. Väldigt få saker i programmering i allmänhet och c++ i synnerhet gör saker underförstått som att avrunda utan att specifikt förklara hur.

EDIT: Kanske ska ge dig en ledtråd också.
Svaret finns i math.h och funktionen round().

http://www.cplusplus.com/reference/cmath/round/

EDIT 2: läste ju inte vad du skrev ordentligt...

Du försöker sätta decimal = heltal vid ett tillfälle då decimal ännu inte har ett värde. Om du initierat decimal till 0.0 där när du skapar den från början så hade det där i alla fall kompilerat och gått att köra men de hade inte direkt varit vettigt

Trädvy Permalänk
Medlem
Plats
127.0.0.1
Registrerad
Maj 2008

ett tips är att initiera variablerna så fort du skapar dom, ex: float decimal = 3.1415, sen kan du skapa alla variabler i början (inget måste utan mest bara estetiskt)

ex:
int main()
{
float decimal = 3.1415;
int heltal = 0;

** KOD **
}

e:
om du har planer på att fortsätta programmera så dumpa: using namespace std
och använd istället ex: std::cout, std::cin
kommer underlätta när du kommer till det stadiet.

"Resistance is futile."

- Georg Ohm

Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011

Det makes no sense att försöka ge heltal det värde som decimal evalueras till innan decimal överhuvudtaget har tilldelats ett värde.

Kom också ihåg att använda [code] när du postar kod, så att den går att läsa.

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Entusiast
Testpilot
Plats
Chalmers
Registrerad
Aug 2011
Skrivet av Selmalagerlöf:

ett tips är att deklarera variablerna så fort du skapar dom, ex: float decimal = 3.1415, sen kan du skapa alla variabler i början (inget måste utan mest bara estetiskt)

ex:
int main()
{
float decimal = 3.1415;
int heltal = 0;

** KOD **
}

Tror du förväxlar deklarera (float decimal) med initiera (decimal = 3.1415).

5930K • Corsair DP 32 GiB • EVGA GTX 980 • 2x Swift PG278Q
Better SweClockersDisplayPort över USB-C

Köp processor för framtiden™, men inte grafikkort.

Trädvy Permalänk
Medlem
Plats
127.0.0.1
Registrerad
Maj 2008
Skrivet av Alling:

Tror du förväxlar deklarera (float decimal) med initiera (decimal = 3.1415).

ingen aning om vad du pratar om?!?!?!?!!?!? tack för att du tillrättavisade mig

"Resistance is futile."

- Georg Ohm

Trädvy Permalänk
Medlem
Registrerad
Sep 2013

float a = 0.4; float b = 0.7; int sum = 0; sum = 'a eller b' + 0.5; cout << sum;

Detta blir väl korrekt avrundat?

Corsair Obsidian 350D
// Asus Maximus VI Gene // Intel i5 4670k H100i // GTX 1060 3GB // Corsair Vengeance 8GBx2 // Corsair AX760 //Samsung 850 Evo 1TB//
_________________________________________________________________________________________

Trädvy Permalänk
Medlem
Registrerad
Aug 2015

Tack för alla snabba svar!

Nu tror jag att jag förstår hur det skall vara (eller iaf som jag ville hur det skulle se ut) och det är följande (rätta mig gärna om det blev tokigt ) :

#include <iostream>

using namespace std;

int main()
{

float decimal;
int heltal;

cout << "Ange ett decimaltal du vill avrunda: ";
cin >> decimal;
heltal = decimal;
cout << "Decimaltalet: " << decimal << " Avrundat blir talet: " << heltal;
return 0;
}

En liten följdfråga på vart man skriver variabler, är det dumt att ange dom i början av koden?
eller är med mer korrekt/lättare att skriva in dom i koden (tex före cin >>) som jag gjort nedan?
Kanske har det betydelse när man skriver större program?

#include <iostream>

using namespace std;

int main()
{

cout << "Ange ett decimaltal du vill avrunda: ";
float decimal;
cin >> decimal;
int heltal;
heltal = decimal;
cout << "Decimaltalet: " << decimal << " Avrundat blir talet: " << heltal;
return 0;
}

Trädvy Permalänk
Medlem
Registrerad
Aug 2015

@Selmalagerlöf:

Jag är just nu på tredje övningen i kursen, så kommer säkert komma till att skippa using namespace std om ett litet tag.
Men tack för tipset!

Trädvy Permalänk
Medlem
Plats
Västervik
Registrerad
Okt 2009

I C var man tvungen att deklarera variabler i början av koden, (egentligen i början av det block den används)

I C++ kan man deklarera en variabel var som helst i koden. Tanken är att att man inte ska skapa variabler förrän man behöver dem.
Tänk att du har en lång funktion med många variabler. Då kan det vara att föredra att deklarera variablerna i anslutning till den del av koden som behöver variabeln, istället för att alla variabler deklareras i en klump i början.

I praktiken kan du tänka så här: Gör på det sättet som du tycker blir tydligast att förstå koden.

Det är också bra att ta för vana att initiera variablerna när du deklarerar dem.

Skulle nog skrivit koden så här:

#include <iostream> using namespace std; int main() { float decimal(0.0f); int heltal(0); cout << "Ange ett decimaltal du vill avrunda: "; cin >> decimal; heltal = (decimal + 0.5f); cout << "Decimaltalet: " << decimal << " Avrundat blir talet: " << heltal; return 0; }

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008
Skrivet av Human_Metal:

I C++ kan man deklarera en variabel var som helst i koden. Tanken är att att man inte ska skapa variabler förrän man behöver dem.
Tänk att du har en lång funktion med många variabler. Då kan det vara att föredra att deklarera variablerna i anslutning till den del av koden som behöver variabeln, istället för att alla variabler deklareras i en klump i början.

I praktiken kan du tänka så här: Gör på det sättet som du tycker blir tydligast att förstå koden.

Det är också bra att ta för vana att initiera variablerna när du deklarerar dem.

Skulle nog skrivit koden så här:

Nä, nu måste jag opponera mig. Jag håller helt med om "Gör på det sättet som du tycker blir tydligast att förstå koden", men gör du verkligen det? Här kommer du givetvis att svara "ja, det gör jag" men att du tycker det är lättast att förstå när det ser ut så här tror jag beror på att du är van att göra så just så här. Men om man inte är van vid att ens kod ser ut på det här sättet, är det då det då det sättet att skriva sin kod som gör det lättast att förstå?

Börjar man programmera i C++ och inte kommer från C finns det väl ingen anledning att börja skriva variablerna i början på funktionen? Du säger ju själv att det är en fördel att kunna deklarera dem var som helst. Varför förespråkar du då att man inte skall använda sig av den finessen? Apa33 skall väl inte lära in ett gammaldags beteende?

Sedan var det det här med initieringen. En stor fördel med att inte deklarera variabler i förväg är att de aldrig befinner sig i ett tillstånd där de inte fått sitt "riktiga" värde och därför inte behöver någon tilldelning av ett dummyvärde. Om man kör den stilen och hittar en deklaration som inte initierar variabeln, då vet man att det är något speciellt men den variabeln. Till exempel att den tilldelas sitt värde från cin eller att den tilldelas indirekt genom referens eller att man exempelvis skickar dess adress till en funktion.

Om vi i TS kodsnutt väntar med att deklarera variabeln heltal tills den tilldelas ett värde, då finns det ingen anledning till att initiera den med ett värde som aldrig kommer användas och avsaknaden av initiering för variabeln decimal signalerar att det finns anledning att vara lite extra uppmärksam när det gäller den variabeln. Blir det inte lättare att förstå vad som händer i funktionen om man inte gör saker i onödan?

int main() { float decimal; cout << "Ange ett decimaltal du vill avrunda: "; cin >> decimal; int heltal = (decimal + 0.5f); cout << "Decimaltalet: " << decimal << " Avrundat blir talet: " << heltal; return 0; }

Trädvy Permalänk
Medlem
Plats
Västervik
Registrerad
Okt 2009
Skrivet av Ingetledigtnamn:

Nä, nu måste jag opponera mig. Jag håller helt med om "Gör på det sättet som du tycker blir tydligast att förstå koden", men gör du verkligen det? Här kommer du givetvis att svara "ja, det gör jag" men att du tycker det är lättast att förstå när det ser ut så här tror jag beror på att du är van att göra så just så här. Men om man inte är van vid att ens kod ser ut på det här sättet, är det då det då det sättet att skriva sin kod som gör det lättast att förstå?

Börjar man programmera i C++ och inte kommer från C finns det väl ingen anledning att börja skriva variablerna i början på funktionen? Du säger ju själv att det är en fördel att kunna deklarera dem var som helst. Varför förespråkar du då att man inte skall använda sig av den finessen? Apa33 skall väl inte lära in ett gammaldags beteende?

Sedan var det det här med initieringen. En stor fördel med att inte deklarera variabler i förväg är att de aldrig befinner sig i ett tillstånd där de inte fått sitt "riktiga" värde och därför inte behöver någon tilldelning av ett dummyvärde. Om man kör den stilen och hittar en deklaration som inte initierar variabeln, då vet man att det är något speciellt men den variabeln. Till exempel att den tilldelas sitt värde från cin eller att den tilldelas indirekt genom referens eller att man exempelvis skickar dess adress till en funktion.

Om vi i TS kodsnutt väntar med att deklarera variabeln heltal tills den tilldelas ett värde, då finns det ingen anledning till att initiera den med ett värde som aldrig kommer användas och avsaknaden av initiering för variabeln decimal signalerar att det finns anledning att vara lite extra uppmärksam när det gäller den variabeln. Blir det inte lättare att förstå vad som händer i funktionen om man inte gör saker i onödan?

Kanske skulle ha skrivit så här: int main() { // Annan programmkod float decimal; int heltal; cout << "Ange ett decimaltal du vill avrunda: "; odv...

Personligen gillar jag att deklarera variabler som har ihop tillsammans, för att markera att de är relaterade.
Jag tycker att det blir tydligt. Andra sätt är också bra. Gäller att hitta en stil man trivs med bara.
Att deklarera 'heltal' som du gör är ju också en bra lösning.

Ska man endast använda 'heltal' för att skriva ut ett avrundat värde vore det bättre att bara casta om variabeln när den skrivs ut

cout << "Decimaltalet: " << decimal << " Avrundat blir talet: " << static_cast<int>(decimal + 0.5f);

Oinitierade variabler kan leda till en del svårhittade buggar, så det kan vara bra att tänka på.

Trädvy Permalänk
Medlem
Plats
Göteborg
Registrerad
Mar 2013

@Apa33:
Som flera tidigare påpekat så gör "heltal = decimal" ingen avrundning utan trukering dvs decimalerna kapas bara av. Testa att t.ex. mata in talet 0.7 i ditt program så får du se vad som händer. Du har fått flera förslag på hur du gör en korrekt avrundning tidigare i tråden.

Trädvy Permalänk
Medlem
Registrerad
Mar 2018

Som tidigare nämnts så avrundas inte talet genom att konvertera till en integer. Använd round() (http://www.cplusplus.com/reference/cmath/round/) funktionen om du vill avrunda.

Att deklarera variabeln vid det första tillfälle du använder den är inte heller alltid rätt, ta följande som exempel:

int blabla() { if(true) { int i = AssignMyInt(); //.... } //i är inte giltig längre.. i = 12345; //Fel! }

Sammanfattning:
Deklarera den så sent som möjligt men gör det i det ytterska scope den används i:

int blabla() { int i; if(true) { i = AssignMyInt(); //.... } //i är fortfarande giltig else i = 12345; }

Sedan är det ju egentligen ren program logik att du ska definiera en variabel innan du läser från den. Det innebär inte att du behöver göra det samtidigt som den deklarerats. Som i ditt fall tilldelas decimal ett värde ifrån cin. Efter att det tilldelats ett värde så ska du tilldela det värdet till din integer. I ditt fall behöver du inte ens spara det i en variabel utan du kan konvertera den direkt i cout << (int)decimal...
Men om vi nu ska titta på vad du faktiskt vill uppnå så ska du använda round som jag först nämnde.

Trädvy Permalänk
Medlem
Plats
Uppsala
Registrerad
Dec 2008
Skrivet av Human_Metal:

[code]
Oinitierade variabler kan leda till en del svårhittade buggar, så det kan vara bra att tänka på.

Visst kommer variabler som inte fått sitt korrekta värde ställa till det, men blir det bättre för att du initierar dem till noll?

Funktionen kommer sannolikt uppvisa samma beteende om man anropar den flera gånger, vilket den kanske inte gör om variabeln råkar innehålla det godtyckliga värde som minnescellen eller registret innehöll vid anropet, men den kommer inte göra mer rätt bara för att du nollar dina variabler i samband med deklarationen.

Trädvy Permalänk
Medlem
Plats
Stockholm
Registrerad
Dec 2004

Sen rekommenderar jag att du använder dig av static_cast i C++ när du konverterar.
Typ:

float f = 3.33; int n = static_cast<int>(f);

Anledning:
https://stackoverflow.com/questions/103512/why-use-static-cas...

[Intel 6700K Skylake] - [EVGA Z170 Stinger mITX] - [Crucial Ballistix Sport DDR4 16GB 2400MHz] - [NCASE M1 chassi] - [KFA2 GTX970 mITX] - [Samsung 840 240GB SSD] - [SilverStone SX500-LG] - [Noctua NH-D9L / NF-F12 PWM / NF-A9 PWM]