Lägg ihop två int's utan addering, för jämförelse

C, C++, Pascal, Assembly, Raspberry, Java, Matlab, Python, BASIC, SQL, PHP, etc.
Användarvisningsbild
toffie
Inlägg: 1785
Blev medlem: 22 juli 2004, 21:38:07
Ort: Töreboda / Stockholm
Kontakt:

Lägg ihop två int's utan addering, för jämförelse

Inlägg av toffie »

Hej på er,

Har helt kört fast i huvudet.. jag kör en Arduino plattform, dvs C språket.

Jag har sparat timme och minut som läses in i en byte array (eepromvarArray). Där jag har timme från (position eepromvarArray[4]) och minut från (position eepromvarArray[5]) m.m.

Dessa skulle jag vilja lägga ihop i en gemensam variabel av valfri typ, så länge jag kan jämföra mot annan likvärdig variabel enligt tid/klocka.

Jag vill alltså ha ex. timme 10 och minut 09 att sitta ihop i en variabel 1009 och givetvis går inte 10 + 9 eftersom det blir 19. Givetvis går inte (10*10) + 9 eftersom det blir 109.. jag behöver verkligen 1009 och jag lyckas verkligen inte...

Anledningen till att jag läser ur EEPROM med timme i en byte och minuter i en byte, är därför att "ramverket" i övrigt är byggt så och jag tyckte det fungerade rätt så bra.

Innan jag kom på att jag behöver jämföra både timme och minut samtidigt så jämförde jag timme med timme och minut med minut, då var det absolut inga problem. Men, utan att ha råkat ut för det, så tror jag att om jag har följande.. att klockan "nu" är säg 1326 och vi jämför med en starttimme som är 10 så är vi ju efter det värdet. Men om vi har en startminut på säg 30 så kommer vi de första 30 minuterna att få fel, varje timme. Därav så började jag titta på att få ihop timme med minut i en variabel för att jämföra det som ett enda värde istället..

Har provat med följande som inte fungerar..

Kod: Markera allt

uint16_t	nowHour			= 0;
uint16_t	nowMinutes		= 0;
uint16_t	nowSeconds		= 0;
uint16_t	nowYear			= 0;
uint16_t	nowMonth			= 0;
uint16_t	nowDay			= 0;
uint16_t	nowWday			= 0;
uint16_t	validYear			= 0;
uint16_t	validMonth		= 0;
uint16_t	validDay			= 0;
uint16_t	validHourFrom		= 0;
uint16_t	validMinFrom		= 0;
uint16_t	validHourUntil		= 0;
uint16_t	validMinUntil		= 0;
uint16_t	validWday			= 0;

validYear		= eepromvarArray[1];
validMonth		= eepromvarArray[2];
validDay		= eepromvarArray[3];
validHourFrom	= eepromvarArray[4];
validMinFrom	= eepromvarArray[5];
validHourUntil	= eepromvarArray[6];
validMinUntil	= eepromvarArray[7];
validWday		= eepromvarArray[8];

nowHour		= tm.Hour;
nowMinutes	= tm.Minute;
tm.Hour och tm.Minute kommer från ett DS1307 bibliotek, tm-Hour och tm.Minute ska vara decimal enligt biblioteket.. men kan inte se att de har specifikt satt värdena som detta.


Med följande kod;

Kod: Markera allt

char validTimeFrom[5];
char validTimeUntil[5];
char timeNow[5];
sprintf(validTimeFrom,	"%.2d%.2d",validHourFrom,validMinFrom);
sprintf(validTimeUntil,	"%.2d%.2d",validHourUntil,validMinUntil);
sprintf(timeNow,		"%.2d%.2d",nowHour,nowMinutes);

if ( validTimeFrom <= timeNow )
{
	Serial.println("Efter starttid");
}
else
{
	Serial.println("Innan starttid");
}

if ( validTimeUntil >= timeNow )
{
	Serial.println("Innan sluttid!");
}
else
{
	Serial.println("Efter sluttid!");
}
.. får jag alltid samma resultat med <= och >=, dvs alltid "innan" det jämförda värdet.

Det som "lurar" mig är ju att om jag kör en Serial.print på validTimeFrom, validTimeUntil, timeNow så ser de ju helt korrekta ut.. Jag får ut validTimeFrom = 1000, validTimeUntil = 2359, timeNow = 1921

Men med checken ovan validTimeFrom <= timeNow så får jag alltid else med "Innan starttid"... Jag vill ju ha att vi är efter starttid.. och det bör det ju vara i detta läge med timeNow = 1921, men är inte så..

Vad jag förmodar så är det därför jag jämför fel sorts värden!??



Har säkerligen missat hälften av vad jag tänkt skriva, även fast jag korrläst..

Blir galen av det här.. alltid "hatat" siffror och de där galna pilarna, större/mindre än, bråkar alltid med mig.. Använder de hur mycket som helst, men jag tror inte att jag förstår dem ändå efter 20 år plus det antal år man gick i skolan, det har helt enkelt aldrig fastnat..



Men det jag vill åstadkomma är hur som helst..

variabel1 = 10
variabel2 = 00

sättas ihop till variabel3 = 1000

Hur!?


Många tack på förhand!
Zeela
Inlägg: 176
Blev medlem: 28 augusti 2008, 11:23:49
Ort: Åtvidaberg
Kontakt:

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av Zeela »

Prova :
variabel3 = variabel1 *100 + variabel2;



.
Kulla
Inlägg: 1264
Blev medlem: 7 januari 2010, 10:06:11
Ort: Sandared
Kontakt:

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av Kulla »

Du kan inte göra det med int, bara med string, så du kan konvertera det i string och sen lägga de ihop

typ variabel3 = String(variabel1) + String (variabel2)

Eller ja, du kan göra det, men då får du räkna ut decimaler och allt annat för att få det som du vill.

variabel 3 = variabel1 * 1000 + variabel2
Användarvisningsbild
Swech
EF Sponsor
Inlägg: 4689
Blev medlem: 6 november 2006, 21:43:35
Ort: Munkedal, Sverige (Sweden)
Kontakt:

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av Swech »

Annars om du jämför timmar och minuter
t.ex starttid 13.24
din tid 13.45

Om starttid (timme) < din tid (timme) så är din tid efter
om starttid (timme) = din tid(timme) så kolla om starttid (minut) < din tid(minut)

Swech
Användarvisningsbild
Icecap
Inlägg: 26106
Blev medlem: 10 januari 2005, 14:52:15
Ort: Aabenraa, Danmark

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av Icecap »

"tm-Hour och tm.Minute ska vara decimal enligt biblioteket..."
Är du SÄKER på att de inte ska vara BCD istället?

Alltså så att värdet 35 anges som 0x35... Nästan alla av DS RTC-kretsar som har datum, timmar, minuter osv. kör nämligen med BCD.

Det är enkelt att omforma om man vill:
binärt värde = ((BCD >> 4) * 10) + (BCD & 0x0F);
Användarvisningsbild
adent
Inlägg: 4094
Blev medlem: 27 november 2008, 22:56:23
Ort: Utanför Jönköping
Kontakt:

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av adent »

Om du verkligen har en siffra för timmar och en för minuter så är det lättaste och mest rätta följande imho:

om variabeln A innehåller timmar och B minuter:

C = A*60+B

Sedan använder du C för att jämföra mot andra siffror av samma typ.
FormerMazda
Inlägg: 6066
Blev medlem: 27 februari 2006, 14:59:36
Ort: Tranås (Jönköping)

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av FormerMazda »

Som nämnt innan:
* Antingen göra om till sträng och jämföra strängarna. Men då kan du bara se om en sträng är lika med en annan sträng såklart. Inte om motsvarande värde i INT är större eller mindre.
* Om det är på samma dygn en tid ska jämföras med en annan så konvertera tiderna till minuter eller sekunder. Sen bara jämföra INTar.

Men spänner det över midnatt, och särskilt över flera dagar med kalenderdagar att ta hänsyn till så blir det mycket jobbigare.

Det här är förmodligen inte applicerbart i detta fall, men när jag ska hålla koll på timers som spänner över flera dagar så har jag i det språk jag jobbar i en timer som räknar sekunder från 1970-nåt-datum-minns-inte-exakt. Då spelar ju inga midnätter eller nyår nån roll.
svanted
Inlägg: 5082
Blev medlem: 30 augusti 2010, 21:20:38
Ort: Umeå

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av svanted »

jag skulle gjort funktioner som gör om klockslag till antal minuter efter midnatt, och sen jämföra dessa

if( timeToMin( 10, 06 ) < timeToMin( 13, 34 ))
{




}
ie
EF Sponsor
Inlägg: 1271
Blev medlem: 23 oktober 2006, 13:12:57
Ort: Tyresö

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av ie »

Som jag förstår det har du två lika arrayer med resp tidsstämpel i samma format (typ ÅÅMMDDHHMMSS).

Då kan du använda memcmp som jämför arrayerna tecken för tecken tills de inte matchar varandra. Resultatet är -1 eller 1 om den ena är mindra resp större än den andra och 0 om de är lika.

/Ingvar
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av arvidb »

toffie skrev:

Kod: Markera allt

char validTimeFrom[5];
char validTimeUntil[5];
char timeNow[5];
sprintf(validTimeFrom,	"%.2d%.2d",validHourFrom,validMinFrom);
sprintf(validTimeUntil,	"%.2d%.2d",validHourUntil,validMinUntil);
sprintf(timeNow,		"%.2d%.2d",nowHour,nowMinutes);

if ( validTimeFrom <= timeNow )
{
	Serial.println("Efter starttid");
}
else
{
	Serial.println("Innan starttid");
}

if ( validTimeUntil >= timeNow )
{
	Serial.println("Innan sluttid!");
}
else
{
	Serial.println("Efter sluttid!");
}
.. får jag alltid samma resultat med <= och >=, dvs alltid "innan" det jämförda värdet.

Det som "lurar" mig är ju att om jag kör en Serial.print på validTimeFrom, validTimeUntil, timeNow så ser de ju helt korrekta ut.. Jag får ut validTimeFrom = 1000, validTimeUntil = 2359, timeNow = 1921

Men med checken ovan validTimeFrom <= timeNow så får jag alltid else med "Innan starttid"... Jag vill ju ha att vi är efter starttid.. och det bör det ju vara i detta läge med timeNow = 1921, men är inte så..

Vad jag förmodar så är det därför jag jämför fel sorts värden!??
Precis. Du kan inte jämföra innehållet i strängar på det sättet. Uttrycket if (validTimeFrom <= timeNow) jämför de två strängarnas position i minnet, inte deras innehåll! Både validTimeFrom och timeNow är ju pekare till början av respektive sträng i minnet.

Som t.ex. adent redan sagt: räkna om till minuter (och strunta i att använda textsträngar) eller jämför direkt mot eepromvarArray med memcmp() som ie tipsar om. Det senare får väl anses som en rätt avancerad programmering så jag rekommenderar absolut att du gör det första - det blir mer kod men betydligt enklare att förstå vad som händer, tror jag.
svanted
Inlägg: 5082
Blev medlem: 30 augusti 2010, 21:20:38
Ort: Umeå

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av svanted »

hur får du ut t.e.x. eepromvarArray[4] till värde "10"?
om det är en char kan det inte beskriva ascii "10" då det är två byte, eller är det en int?

"uint16_t validHourFrom" är ju en 16 bitars int, och måste behandlas som en int

typ



uint16_t fromMinutes, untilMinutes;


fromMinutes = (validHourFrom * 60) + validMinFrom;

nowMinutes = (nowHour * 60) + nowMinues;


if ( fromMinutes <= nowMinutes )
{
Serial.println("Efter starttid");
}

e.d.
Användarvisningsbild
arvidb
Inlägg: 4537
Blev medlem: 8 maj 2004, 12:56:24
Ort: Stockholm

Re: Lägg ihop två int's utan addering, för jämförelse

Inlägg av arvidb »

Han skriver ju att han "läser ur EEPROM med timme i en byte och minuter i en byte", så jag tolkar det som att eepromvarArray är en byte-array. Och i så fall funkar det ju (varje position kan lagra värde 0-255).

Att separera år, månader, dagar, timmar, minuter och sekunder istället för att bara räkna sekunder är för övrigt samma misstag som Microsoft gjorde för att lagra tid i DOS, i MS DOS Date & Time Format: 32 bitar där 7 bitar används för att representera antalet år från 1980 (år 1980-2108), 4 bitar används för månad, 5 bitar för dag i månaden, 5 bitar för timmar (0-23), 6 bitar för minuter (0-59), och 5 för sekunder (0-30, det vill säga upplösningen är 2 sekunder).

Hade de använt alla 32 bitarna för att räkna sekunder istället så hade de fått sekundupplösning och ett tidsspann på 136 år istället för 127 år...
Skriv svar