Just nu i M3-nätverket
Gå till innehåll
MissyMalinto

Kontrollera om kontrollsiffran i personnummer stämmer

Rekommendera Poster

Guraknugen
Postad (redigerade)

Kom förresten på att min variant också var lite onödigt lång och går att förkorta avsevärt bara genom att ta bort allt som räknas ut i onödan (multiplicering med 1 och liknande):

=REST(10-REST(HELTAL(EXTEXT($A1;1;1)/5)+REST(EXTEXT($A1;1;1)*2;10)+
				REST(EXTEXT($A1;2;1);10)+
      HELTAL(EXTEXT($A1;3;1)/5)+REST(EXTEXT($A1;3;1)*2;10)+
				REST(EXTEXT($A1;4;1);10)+
      HELTAL(EXTEXT($A1;5;1)/5)+REST(EXTEXT($A1;5;1)*2;10)+
				REST(EXTEXT($A1;6;1);10)+
      HELTAL(EXTEXT($A1;7;1)/5)+REST(EXTEXT($A1;7;1)*2;10)+
				REST(EXTEXT($A1;8;1);10)+
      HELTAL(EXTEXT($A1;9;1)/5)+REST(EXTEXT($A1;9;1)*2;10);10);10)

Blir dock fortfarande längre än den kortare varianten med ”passiva matriser”, som säkert också går att förkorta på motsvarande sätt även om inte jag lyckades så bra med det. Fick fel resultat och orkade inte felsöka (är magsjuk för tillfället och har inte så mycket ork…).

 

Fortfarande har jag med saker som alltid blir noll… Så här blir det ännu kortare, med samma resultat:

=REST(10-REST(HELTAL(EXTEXT($A1;1;1)/5)+REST(EXTEXT($A1;1;1)*2;10)+
				REST(EXTEXT($A1;2;1);10)+
				REST(EXTEXT($A1;3;1)*2;10)+
				REST(EXTEXT($A1;4;1);10)+
				REST(EXTEXT($A1;5;1)*2;10)+
				REST(EXTEXT($A1;6;1);10)+
      HELTAL(EXTEXT($A1;7;1)/5)+REST(EXTEXT($A1;7;1)*2;10)+
				REST(EXTEXT($A1;8;1);10)+
      HELTAL(EXTEXT($A1;9;1)/5)+REST(EXTEXT($A1;9;1)*2;10);10);10)

 

Eller som den ser ut i formelraden:

=REST(10-REST(HELTAL(EXTEXT($A1;1;1)/5)+REST(EXTEXT($A1;1;1)*2;10)+REST(EXTEXT($A1;2;1);10)+REST(EXTEXT($A1;3;1)*2;10)+REST(EXTEXT($A1;4;1);10)+REST(EXTEXT($A1;5;1)*2;10)+REST(EXTEXT($A1;6;1);10)+HELTAL(EXTEXT($A1;7;1)/5)+REST(EXTEXT($A1;7;1)*2;10)+REST(EXTEXT($A1;8;1);10)+HELTAL(EXTEXT($A1;9;1)/5)+REST(EXTEXT($A1;9;1)*2;10);10);10)

Fortfarande ganska långt, men troligen snabbare eftersom färre saker behöver räknas ut.

 

Om man läser #23 så ser man dessutom att varianten där med två produktsummor gör samma sak som den jag nyss skrev. Hade jag studerat den lite närmare med en gång hade jag sluppit att skriva väldigt mycket av det jag skrivit nyligen. Så kan det gå…

Men det var kul att komma fram till det själv, även om det tog tid för min långsamma hjärna… ha ha ha…

 

Min fundering nu är vilken som går snabbast. Oväsentligt när man bara använder uttrycket i en cell, men ska man fylla en kolumn med några hundra rader kan det kanske ha betydelse. Har dock ingen bra idé hur man testar detta på ett vetenskapligt sätt. Makron är enkla att ta tid på, men cellformler? Kanske lika enkelt, men jag har aldrig försökt…

Redigerad av Guraknugen

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
MH_

Min gissning är att det tar ungefär lika lång tid. Matrisformler anses vara långsamma, men det är när man slår upp värden i långa cellintervall. Nu gör ju formlerna exakt samma sak så de borde vara jämnsnabba, möjligtvis en viss fördel till dina "manuella".

 

med 65 000 personnummer så skulle du möjligtvis tjäna någon 1/10 sekund på att slänga in "TEXTNUM" runt varje EXTEXT. Formeln blir längre men programmet slipper gissa datatyp. Misslyckande för "min" formel berodde ju på att typkonverteringen var svår att hantera för programmet.

 

Den enda gången jag testar formelhastighet brukar vara ofrivilligt. T.ex när man behöver skapa en ny variabel i en lång tabell. Då märks det tydligt att matrisformler har det jobbigt, men då brukar formeln titta på hela kolumnen, det är klart att det blir jobbigt när formeln upprepas på varje rad

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
Guraknugen
Postad (redigerade)

Min gissning är att det tar ungefär lika lång tid. Matrisformler anses vara långsamma, men det är när man slår upp värden i långa cellintervall. Nu gör ju formlerna exakt samma sak så de borde vara jämnsnabba, möjligtvis en viss fördel till dina "manuella".

 

med 65 000 personnummer så skulle du möjligtvis tjäna någon 1/10 sekund på att slänga in "TEXTNUM" runt varje EXTEXT. Formeln blir längre men programmet slipper gissa datatyp. Misslyckande för "min" formel berodde ju på att typkonverteringen var svår att hantera för programmet.

 

Den enda gången jag testar formelhastighet brukar vara ofrivilligt. T.ex när man behöver skapa en ny variabel i en lång tabell. Då märks det tydligt att matrisformler har det jobbigt, men då brukar formeln titta på hela kolumnen, det är klart att det blir jobbigt när formeln upprepas på varje rad

 

Såg att det gick att göra din ännu lite kortare i alla fall, om än kanske inte snabbare: Byt ut AVKORTA mot HELTAL… Inte nog med att HELTAL har färre bokstäver, du slipper ett argument också. Har ingen som helst praktisk betydelse, men nu har jag sagt det i alla fall.

 

En sak som jag ibland gjort som visat sig gå fruktansvärt långsamt, i alla fall i LibreOffice, är när man har villkorlig formatering på ett stort område, där man i villkoren har med saker som MAX() eller MIN(), eller värre, där argumenten för dessa är en fast referens till ett stort område. Om området är 10 000 rader, 10 kolumner och om MAX() exempelvis inkluderar en kolumn på 10 000 rader, så kommer alltså varje cell i det området att gås igenom 10 000 · 10 000 · 10 gånger… per villkor i värsta fall! Alltså en miljard gånger…

Där kan man vinna mycket på att räkna ut MAX()- och/eller MIN()-funktionerna en gång för alla i var sin cell istället (om referenserna är fasta, alltså typ MAX($A$1:$A$10000), så behöver de bara räknas ut en enda gång var. Egna tester tyder på att detta är fruktansvärt väsentligt för snabbheten, i alla fall i LibreOffice. Har som sagt ingen möjlighet att testa i Excel.

Redigerad av Guraknugen

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
MH_

Japp, det är samma sak. Min/max/summa är ju också matrisformler, även om matrisen är en enda vektor.

 

Det är när man råkar skriva en sån formel och ser "procent färdig" ticka låååååångsamt som man börjar kalla sig själv fula saker :wacko: sen börjar man svettas när man inser att man inte sparat bladet på 3 timmar :ph34r:

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
Guraknugen

Japp, det är samma sak. Min/max/summa är ju också matrisformler, även om matrisen är en enda vektor.

 

Det är när man råkar skriva en sån formel och ser "procent färdig" ticka låååååångsamt som man börjar kalla sig själv fula saker :wacko: sen börjar man svettas när man inser att man inte sparat bladet på 3 timmar :ph34r:

 

I LibreOffice tickar det dessutom inga procent, det går bara inte att göra något på ett bra tag… om jag inte minns fel, det var ett tag sedan jag gjorde det misstaget nu.

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
MH_

Märkligt att man hamnar i gamla eforumtrådar när man googlar egna problem.

 

Med Modern excel landade jag til sist i den ganska nätta formeln:

 

=LET(nr;EXTEXT(BYT.UT(A2;"-";"");SEKVENS(10);1)*(1+ÄRUDDA(SEKVENS(10)));OM(REST(SUMMA(OM(nr>9;nr-9;nr));10)=0;"ok";"Fel kontr"))

Allt var inte bättre förr

 

=LET(

nr;EXTEXT(BYT.UT(A2;"-";"");SEKVENS(10);1)*(1+ÄRUDDA(SEKVENS(10)));

OM(

REST(SUMMA(OM(nr>9;nr-9;nr));10)=0;

"ok";"Fel kontr"))

 

 

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
Lars G

Ett litet inlägg i den långa debatten om Kontrollera Personnummer

Metoden för att räkna ut kontrollsifran i personnummret kallas för
Luhnalgoritmen (Hans Peter Luhn på IBM), även kallad modulus-10-algoritmen.
Varannan siffra multipliceras med 2. Om resultatet blir 10 eller mer tas tvärsumman.

I min matteskola fick man lära sig att det gör man enklast med KVOT och REST för
att få heltalet resp. det som blir över.
EX.  45  KVOT(45;10) ger 4,  REST(45;10) ger 5.

Min formel för beräkning Pnr: blir därför:
Ta bort ev. bindestreck först med  BYT.UT(A1;"-";"")

=REST(10-(REST(KVOT(EXTEXT($A1;1;1)*2;10)+REST(EXTEXT($A1;1;1)*2;10)+
EXTEXT($A1;2;1)+
KVOT(EXTEXT($A1;3;1)*2;10)+REST(EXTEXT($A1;3;1)*2;10)+
EXTEXT($A1;4;1)+
KVOT(EXTEXT($A1;5;1)*2;10)+REST(EXTEXT($A1;5;1)*2;10)+
EXTEXT($A1;6;1)+
KVOT(EXTEXT($A1;7;1)*2;10)+REST(EXTEXT($A1;7;1)*2;10)+
EXTEXT($A1;8;1)+
KVOT(EXTEXT($A1;9;1)*2;10)+REST(EXTEXT($A1;9;1)*2;10);10));10)

Obs: att den siffran som multipliceras med 1 tar man bara ut med EXTEXT.
När man sedan har fått en slutsumma skall den behandlas.

Får man en slutsumma t.ex 44 så blir kontrollsiffran närmast högre heltal d.v.s 50-44=6
eller om man så vill 10-4.
I EXCEL enkelt med formeln =REST(10-REST(44;10);10)
OBS:  2 REST funktioner p.g.a att om slutsumman är jämt 10-tal skall kontrollsiffran bli 0 och inte 10.

Samma sak gäller även för Monshis fina funktion i VBA
KontrolleraKontrollsiffra = ((10 - (summa - Int(summa / 10) * 10)) = temp)
bör eg.  vara
KontrolleraKontrollsiffra = ((10 - summa Mod 10) Mod 10 = rest)

MH_:s formel med produktsumma verkar också fungera.

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
MH_

Hmm, kan man använda det för att göra den "moderna" excelvarianten snyggare? Räkna ut kontrollsiffra:

=LET(sekv;SEKVENS(9);

Pntxt;HÖGER(BYT.UT(A2;"-";"");10);

nr;EXTEXT(Pntxt;sekv;1)*(1+ÄRUDDA(sekv));

REST(REST(10-SUMMA(KVOT(nr;10);REST(nr;10));10);10))

 

eller, om man bara vill kontrollera att kontrollsiffran stämmer (dvs att REST(10)=0 när man inkluderar kontrollsiffran i summan). 

=LET(sekv;SEKVENS(10);
Pntxt;HÖGER(BYT.UT(A2;"-";"");10);
nr;EXTEXT(Pntxt;sekv;1)*(1+ÄRUDDA(sekv));
REST(SUMMA(KVOT(nr;10);REST(nr;10));10)=0)

 

Nja, kanske inte kortare, men det stämmer bättre med alla instruktioner som finns.

 

METOD

Sekvensen 1-9 använder vi flera gånger så den skapar vi:

=LET(sekv;SEKVENS(9);

Jag tänker mig att man städar bort streck och eventuell sekelsiffra med:

=LET(Pntxt;HÖGER(BYT.UT(A2;"-";"");10);

Det blir ju lite längre än vanligt. Men med LET behöver man bara ange det en gång.

Och för att få fram en nummerserie där var annan är dubblerad 

nr;TEXTNUM(EXTEXT(Pntxt;sekv;1))*(1+ÄRUDDA(sekv));

och till sist, för att få fram kontrollsiffran

REST(REST(10-SUMMA(KVOT(nr;10);REST(nr;10));10);10))

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser
Lars G

Här är en rutin för Personnr: som är kortast av alla jag hittills sett och som jag hitta på ett forum på nätet.
Har konfererat med MH_  och han tyckte den var snygg och borde publiceras här på eforum.
Här är den som ger kontrollsiffran
=REST(10-(SUMMA(RUNDA.UPP(REST(EXTEXT(A1;{1;2;3;4;5;6;7;8;9};1)*{2;1;2;1;2;1;2;1;2};9,5);1)));10).
Persionnummer i ruta A1 utan bindestreck.

Det som är problemet är ju tvärsumman när multiplikation med 2 blir 10 eller mer
Det är talen 5, 6, 7, 8, 9 d.v.s 10, 12, 14, 16 och 18. 
En rutin i excel som fixar tvärsumman på ett elegant sätt är med den sällan använda funktionen
REST med 9,5  och sedan RUNDA.UPP med 1   =RUNDA.UPP(REST("temp";9,5);1).
Den ger 1, 3, 5, 7 och 9 på 10, 12, 14, 16 och 18.
Som ex. Delar man 12 med 9,5 blir det kvar 2,5. RUNDA.UPP med 1 ger då 3, = tvärsumman.
Allt i formeln handlar om REST. 
Det är kanske därför det heter modulos-formeln när man ska beräkna kontrollsiffran.  
REST heter MOD på engelska.
9,5 kan variera med något mellan 9 och 10. (9,5 är taget mittimellan)

Tar man med alla 10 siffror ger denna rutin SANT eller FALSKT på personnummret. MH_:s tillägg.
=REST(10-(SUMMA(RUNDA.UPP(REST(EXTEXT(A1;{1;2;3;4;5;6;7;8;9;10};1)*{2;1;2;1;2;1;2;1;2;1};9,5);1)));10)=0

Skall man kunna kolla även med bindesteck i Pnr får man lägga till så att det blir

=REST(10-(SUMMA(RUNDA.UPP(REST(EXTEXT(BYT.UT(A1;"-";"");{1;2;3;4;5;6;7;8;9;10};1)*{2;1;2;1;2;1;2;1;2;1};9,5);1)));10)=0

Kortare än så blir det knappast i Excel.

LARS G

Dela detta inlägg


Länk till inlägg
Dela på andra webbplatser

Skapa ett konto eller logga in för att kommentera

Du måste vara medlem för att kunna kommentera

Skapa ett konto

Skapa ett nytt konto på vårt forum. Det är lätt!

Registrera ett nytt konto

Logga in

Redan medlem? Logga in här.

Logga in nu



×
×
  • Skapa nytt...