code 128 barcode in c# wrong check digit for one barcode - c#

I have been using the code from here to convert three digit numbers to barcodes for scanning in the company I work for.
I have only found a problem with one barcode. When it encodes "002" it outputs "Ì002 Î". I have found that this will not scan with the space. With much time searching and looking for what should be in that space and what scans. I found that the barcode generator generator code from here has the  as the check character.
Now for my question How could I change the code to encode that correctly? Or,Is there another FREE code sample that I could implement to get the code 128 barcode?
I have it implemented like
MEKBarcodeLBL.Text = HazmatLabels.Classes.BarcodeConverter128.StringToBarcode(MEKScrapLBL.Text).PadLeft(3, '0');
Thanks in advance for all your help!!!!
BarcodeConverter128.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace HazmatLabels.Classes
{
/// <summary>
/// Code 128
/// Convert an input string to the equivilant string including start and stop characters.
/// This object compresses the values to the shortest possible code 128 barcode format
/// </summary>
public static class BarcodeConverter128
{
/// <summary>
/// Converts an input string to the equivilant string, that need to be produced using the 'Code 128' font.
/// </summary>
/// <param name="value">String to be encoded</param>
/// <returns>Encoded string start/stop and checksum characters included</returns>
public static string StringToBarcode(string value)
{
// Parameters : a string
// Return : a string which give the bar code when it is dispayed with CODE128.TTF font
// : an empty string if the supplied parameter is no good
int charPos, minCharPos;
int currentChar, checksum;
bool isTableB = true, isValid = true;
string returnValue = string.Empty;
if (value.Length > 0)
{
// Check for valid characters
for (int charCount = 0; charCount < value.Length; charCount++)
{
//currentChar = char.GetNumericValue(value, charPos);
currentChar = (int)char.Parse(value.Substring(charCount, 1));
if (!(currentChar >= 32 && currentChar <= 126))
{
isValid = false;
break;
}
}
// Barcode is full of ascii characters, we can now process it
if (isValid)
{
charPos = 0;
while (charPos < value.Length)
{
if (isTableB)
{
// See if interesting to switch to table C
// yes for 4 digits at start or end, else if 6 digits
if (charPos == 0 || charPos + 4 == value.Length)
minCharPos = 4;
else
minCharPos = 6;
minCharPos = BarcodeConverter128.IsNumber(value, charPos, minCharPos);
if (minCharPos < 0)
{
// Choice table C
if (charPos == 0)
{
// Starting with table C
returnValue = ((char)205).ToString(); // char.ConvertFromUtf32(205);
}
else
{
// Switch to table C
returnValue = returnValue + ((char)199).ToString();
}
isTableB = false;
}
else
{
if (charPos == 0)
{
// Starting with table B
returnValue = ((char)204).ToString(); // char.ConvertFromUtf32(204);
}
}
}
if (!isTableB)
{
// We are on table C, try to process 2 digits
minCharPos = 2;
minCharPos = BarcodeConverter128.IsNumber(value, charPos, minCharPos);
if (minCharPos < 0) // OK for 2 digits, process it
{
currentChar = int.Parse(value.Substring(charPos, 2));
currentChar = currentChar < 95 ? currentChar + 32 : currentChar + 100;
returnValue = returnValue + ((char)currentChar).ToString();
charPos += 2;
}
else
{
// We haven't 2 digits, switch to table B
returnValue = returnValue + ((char)200).ToString();
isTableB = true;
}
}
if (isTableB)
{
// Process 1 digit with table B
returnValue = returnValue + value.Substring(charPos, 1);
charPos++;
}
}
// Calculation of the checksum
checksum = 0;
for (int loop = 0; loop < returnValue.Length; loop++)
{
currentChar = (int)char.Parse(returnValue.Substring(loop, 1));
currentChar = currentChar < 127 ? currentChar - 32 : currentChar - 100;
if (loop == 0)
checksum = currentChar;
else
checksum = (checksum + (loop * currentChar)) % 103;
}
// Calculation of the checksum ASCII code
checksum = checksum < 95 ? checksum + 32 : checksum + 100;
// Add the checksum and the STOP
returnValue = returnValue +
((char)checksum).ToString() +
((char)206).ToString();
}
}
return returnValue;
}
private static int IsNumber(string InputValue, int CharPos, int MinCharPos)
{
// if the MinCharPos characters from CharPos are numeric, then MinCharPos = -1
MinCharPos--;
if (CharPos + MinCharPos < InputValue.Length)
{
while (MinCharPos >= 0)
{
if ((int)char.Parse(InputValue.Substring(CharPos + MinCharPos, 1)) < 48
|| (int)char.Parse(InputValue.Substring(CharPos + MinCharPos, 1)) > 57)
{
break;
}
MinCharPos--;
}
}
return MinCharPos;
}
}
}

This is the other code and I am not sure on how to implement it.
Code128Rendering.cs
using System;
using System.Drawing;
using System.Diagnostics;
namespace GenCode128
{
/// <summary>
/// Summary description for Code128Rendering.
/// </summary>
public static class Code128Rendering
{
#region Code patterns
// in principle these rows should each have 6 elements
// however, the last one -- STOP -- has 7. The cost of the
// extra integers is trivial, and this lets the code flow
// much more elegantly
private static readonly int[,] cPatter
ns =
{
{2,1,2,2,2,2,0,0}, // 0
{2,2,2,1,2,2,0,0}, // 1
{2,2,2,2,2,1,0,0}, // 2
{1,2,1,2,2,3,0,0}, // 3
{1,2,1,3,2,2,0,0}, // 4
{1,3,1,2,2,2,0,0}, // 5
{1,2,2,2,1,3,0,0}, // 6
{1,2,2,3,1,2,0,0}, // 7
{1,3,2,2,1,2,0,0}, // 8
{2,2,1,2,1,3,0,0}, // 9
{2,2,1,3,1,2,0,0}, // 10
{2,3,1,2,1,2,0,0}, // 11
{1,1,2,2,3,2,0,0}, // 12
{1,2,2,1,3,2,0,0}, // 13
{1,2,2,2,3,1,0,0}, // 14
{1,1,3,2,2,2,0,0}, // 15
{1,2,3,1,2,2,0,0}, // 16
{1,2,3,2,2,1,0,0}, // 17
{2,2,3,2,1,1,0,0}, // 18
{2,2,1,1,3,2,0,0}, // 19
{2,2,1,2,3,1,0,0}, // 20
{2,1,3,2,1,2,0,0}, // 21
{2,2,3,1,1,2,0,0}, // 22
{3,1,2,1,3,1,0,0}, // 23
{3,1,1,2,2,2,0,0}, // 24
{3,2,1,1,2,2,0,0}, // 25
{3,2,1,2,2,1,0,0}, // 26
{3,1,2,2,1,2,0,0}, // 27
{3,2,2,1,1,2,0,0}, // 28
{3,2,2,2,1,1,0,0}, // 29
{2,1,2,1,2,3,0,0}, // 30
{2,1,2,3,2,1,0,0}, // 31
{2,3,2,1,2,1,0,0}, // 32
{1,1,1,3,2,3,0,0}, // 33
{1,3,1,1,2,3,0,0}, // 34
{1,3,1,3,2,1,0,0}, // 35
{1,1,2,3,1,3,0,0}, // 36
{1,3,2,1,1,3,0,0}, // 37
{1,3,2,3,1,1,0,0}, // 38
{2,1,1,3,1,3,0,0}, // 39
{2,3,1,1,1,3,0,0}, // 40
{2,3,1,3,1,1,0,0}, // 41
{1,1,2,1,3,3,0,0}, // 42
{1,1,2,3,3,1,0,0}, // 43
{1,3,2,1,3,1,0,0}, // 44
{1,1,3,1,2,3,0,0}, // 45
{1,1,3,3,2,1,0,0}, // 46
{1,3,3,1,2,1,0,0}, // 47
{3,1,3,1,2,1,0,0}, // 48
{2,1,1,3,3,1,0,0}, // 49
{2,3,1,1,3,1,0,0}, // 50
{2,1,3,1,1,3,0,0}, // 51
{2,1,3,3,1,1,0,0}, // 52
{2,1,3,1,3,1,0,0}, // 53
{3,1,1,1,2,3,0,0}, // 54
{3,1,1,3,2,1,0,0}, // 55
{3,3,1,1,2,1,0,0}, // 56
{3,1,2,1,1,3,0,0}, // 57
{3,1,2,3,1,1,0,0}, // 58
{3,3,2,1,1,1,0,0}, // 59
{3,1,4,1,1,1,0,0}, // 60
{2,2,1,4,1,1,0,0}, // 61
{4,3,1,1,1,1,0,0}, // 62
{1,1,1,2,2,4,0,0}, // 63
{1,1,1,4,2,2,0,0}, // 64
{1,2,1,1,2,4,0,0}, // 65
{1,2,1,4,2,1,0,0}, // 66
{1,4,1,1,2,2,0,0}, // 67
{1,4,1,2,2,1,0,0}, // 68
{1,1,2,2,1,4,0,0}, // 69
{1,1,2,4,1,2,0,0}, // 70
{1,2,2,1,1,4,0,0}, // 71
{1,2,2,4,1,1,0,0}, // 72
{1,4,2,1,1,2,0,0}, // 73
{1,4,2,2,1,1,0,0}, // 74
{2,4,1,2,1,1,0,0}, // 75
{2,2,1,1,1,4,0,0}, // 76
{4,1,3,1,1,1,0,0}, // 77
{2,4,1,1,1,2,0,0}, // 78
{1,3,4,1,1,1,0,0}, // 79
{1,1,1,2,4,2,0,0}, // 80
{1,2,1,1,4,2,0,0}, // 81
{1,2,1,2,4,1,0,0}, // 82
{1,1,4,2,1,2,0,0}, // 83
{1,2,4,1,1,2,0,0}, // 84
{1,2,4,2,1,1,0,0}, // 85
{4,1,1,2,1,2,0,0}, // 86
{4,2,1,1,1,2,0,0}, // 87
{4,2,1,2,1,1,0,0}, // 88
{2,1,2,1,4,1,0,0}, // 89
{2,1,4,1,2,1,0,0}, // 90
{4,1,2,1,2,1,0,0}, // 91
{1,1,1,1,4,3,0,0}, // 92
{1,1,1,3,4,1,0,0}, // 93
{1,3,1,1,4,1,0,0}, // 94
{1,1,4,1,1,3,0,0}, // 95
{1,1,4,3,1,1,0,0}, // 96
{4,1,1,1,1,3,0,0}, // 97
{4,1,1,3,1,1,0,0}, // 98
{1,1,3,1,4,1,0,0}, // 99
{1,1,4,1,3,1,0,0}, // 100
{3,1,1,1,4,1,0,0}, // 101
{4,1,1,1,3,1,0,0}, // 102
{2,1,1,4,1,2,0,0}, // 103
{2,1,1,2,1,4,0,0}, // 104
{2,1,1,2,3,2,0,0}, // 105
{2,3,3,1,1,1,2,0} // 106
};
#endregion Code patterns
private const int cQuietWidth = 10;
/// <summary>
/// Make an image of a Code128 barcode for a given string
/// </summary>
/// <param name="InputData">Message to be encoded</param>
/// <param name="BarWeight">Base thickness for bar width (1 or 2 works well)</param>
/// <param name="AddQuietZone">Add required horiz margins (use if output is tight)</param>
/// <returns>An Image of the Code128 barcode representing the message</returns>
public static Image MakeBarcodeImage(string InputData, int BarWeight, bool AddQuietZone)
{
// get the Code128 codes to represent the message
Code128Content content = new Code128Content(InputData);
int[] codes = content.Codes;
int width, height;
width = ((codes.Length - 3) * 11 + 35) * BarWeight;
height = Convert.ToInt32(System.Math.Ceiling(Convert.ToSingle(width) * .15F));
if (AddQuietZone)
{
width += 2 * cQuietWidth * BarWeight; // on both sides
}
// get surface to draw on
Image myimg = new System.Drawing.Bitmap(width, height);
using (Graphics gr = Graphics.FromImage(myimg))
{
// set to white so we don't have to fill the spaces with white
gr.FillRectangle(System.Drawing.Brushes.White, 0, 0, width, height);
// skip quiet zone
int cursor = AddQuietZone ? cQuietWidth * BarWeight : 0;
for (int codeidx = 0; codeidx < codes.Length; codeidx++)
{
int code = codes[codeidx];
// take the bars two at a time: a black and a white
for (int bar = 0; bar < 8; bar += 2)
{
int barwidth = cPatterns[code, bar] * BarWeight;
int spcwidth = cPatterns[code, bar + 1] * BarWeight;
// if width is zero, don't try to draw it
if (barwidth > 0)
{
gr.FillRectangle(System.Drawing.Brushes.Black, cursor, 0, barwidth, height);
}
// note that we never need to draw the space, since we
// initialized the graphics to all white
// advance cursor beyond this pair
cursor += (barwidth + spcwidth);
}
}
}
return myimg;
}
}
}
Code128Content.cs
using System;
using System.Text;
namespace GenCode128
{
public enum CodeSet
{
CodeA
, CodeB
// ,CodeC // not supported
}
/// <summary>
/// Represent the set of code values to be output into barcode form
/// </summary>
public class Code128Content
{
private int[] mCodeList;
/// <summary>
/// Create content based on a string of ASCII data
/// </summary>
/// <param name="AsciiData">the string that should be represented</param>
public Code128Content(string AsciiData)
{
mCodeList = StringToCode128(AsciiData);
}
/// <summary>
/// Provides the Code128 code values representing the object's string
/// </summary>
public int[] Codes
{
get
{
return mCodeList;
}
}
/// <summary>
/// Transform the string into integers representing the Code128 codes
/// necessary to represent it
/// </summary>
/// <param name="AsciiData">String to be encoded</param>
/// <returns>Code128 representation</returns>
private int[] StringToCode128(string AsciiData)
{
// turn the string into ascii byte data
byte[] asciiBytes = Encoding.ASCII.GetBytes(AsciiData);
// decide which codeset to start with
Code128Code.CodeSetAllowed csa1 = asciiBytes.Length > 0 ? Code128Code.CodesetAllowedForChar(asciiBytes[0]) : Code128Code.CodeSetAllowed.CodeAorB;
Code128Code.CodeSetAllowed csa2 = asciiBytes.Length > 0 ? Code128Code.CodesetAllowedForChar(asciiBytes[1]) : Code128Code.CodeSetAllowed.CodeAorB;
CodeSet currcs = GetBestStartSet(csa1, csa2);
// set up the beginning of the barcode
System.Collections.ArrayList codes = new System.Collections.ArrayList(asciiBytes.Length + 3); // assume no codeset changes, account for start, checksum, and stop
codes.Add(Code128Code.StartCodeForCodeSet(currcs));
// add the codes for each character in the string
for (int i = 0; i < asciiBytes.Length; i++)
{
int thischar = asciiBytes[i];
int nextchar = asciiBytes.Length > (i + 1) ? asciiBytes[i + 1] : -1;
codes.AddRange(Code128Code.CodesForChar(thischar, nextchar, ref currcs));
}
// calculate the check digit
int checksum = (int)(codes[0]);
for (int i = 1; i < codes.Count; i++)
{
checksum += i * (int)(codes[i]);
}
codes.Add(checksum % 103);
codes.Add(Code128Code.StopCode());
int[] result = codes.ToArray(typeof(int)) as int[];
return result;
}
/// <summary>
/// Determines the best starting code set based on the the first two
/// characters of the string to be encoded
/// </summary>
/// <param name="csa1">First character of input string</param>
/// <param name="csa2">Second character of input string</param>
/// <returns>The codeset determined to be best to start with</returns>
private CodeSet GetBestStartSet(Code128Code.CodeSetAllowed csa1, Code128Code.CodeSetAllowed csa2)
{
int vote = 0;
vote += (csa1 == Code128Code.CodeSetAllowed.CodeA) ? 1 : 0;
vote += (csa1 == Code128Code.CodeSetAllowed.CodeB) ? -1 : 0;
vote += (csa2 == Code128Code.CodeSetAllowed.CodeA) ? 1 : 0;
vote += (csa2 == Code128Code.CodeSetAllowed.CodeB) ? -1 : 0;
return (vote > 0) ? CodeSet.CodeA : CodeSet.CodeB; // ties go to codeB due to my own prejudices
}
}
/// <summary>
/// Static tools for determining codes for individual characters in the content
/// </summary>
public static class Code128Code
{
#region Constants
private const int cSHIFT = 98;
private const int cCODEA = 101;
private const int cCODEB = 100;
private const int cSTARTA = 103;
private const int cSTARTB = 104;
private const int cSTOP = 106;
#endregion
/// <summary>
/// Get the Code128 code value(s) to represent an ASCII character, with
/// optional look-ahead for length optimization
/// </summary>
/// <param name="CharAscii">The ASCII value of the character to translate</param>
/// <param name="LookAheadAscii">The next character in sequence (or -1 if none)</param>
/// <param name="CurrCodeSet">The current codeset, that the returned codes need to follow;
/// if the returned codes change that, then this value will be changed to reflect it</param>
/// <returns>An array of integers representing the codes that need to be output to produce the
/// given character</returns>
public static int[] CodesForChar(int CharAscii, int LookAheadAscii, ref CodeSet CurrCodeSet)
{
int[] result;
int shifter = -1;
if (!CharCompatibleWithCodeset(CharAscii, CurrCodeSet))
{
// if we have a lookahead character AND if the next character is ALSO not compatible
if ((LookAheadAscii != -1) && !CharCompatibleWithCodeset(LookAheadAscii, CurrCodeSet))
{
// we need to switch code sets
switch (CurrCodeSet)
{
case CodeSet.CodeA:
shifter = cCODEB;
CurrCodeSet = CodeSet.CodeB;
break;
case CodeSet.CodeB:
shifter = cCODEA;
CurrCodeSet = CodeSet.CodeA;
break;
}
}
else
{
// no need to switch code sets, a temporary SHIFT will suffice
shifter = cSHIFT;
}
}
if (shifter != -1)
{
result = new int[2];
result[0] = shifter;
result[1] = CodeValueForChar(CharAscii);
}
else
{
result = new int[1];
result[0] = CodeValueForChar(CharAscii);
}
return result;
}
/// <summary>
/// Tells us which codesets a given character value is allowed in
/// </summary>
/// <param name="CharAscii">ASCII value of character to look at</param>
/// <returns>Which codeset(s) can be used to represent this character</returns>
public static CodeSetAllowed CodesetAllowedForChar(int CharAscii)
{
if (CharAscii >= 32 && CharAscii <= 95)
{
return CodeSetAllowed.CodeAorB;
}
else
{
return (CharAscii < 32) ? CodeSetAllowed.CodeA : CodeSetAllowed.CodeB;
}
}
/// <summary>
/// Determine if a character can be represented in a given codeset
/// </summary>
/// <param name="CharAscii">character to check for</param>
/// <param name="currcs">codeset context to test</param>
/// <returns>true if the codeset contains a representation for the ASCII character</returns>
public static bool CharCompatibleWithCodeset(int CharAscii, CodeSet currcs)
{
CodeSetAllowed csa = CodesetAllowedForChar(CharAscii);
return csa == CodeSetAllowed.CodeAorB
|| (csa == CodeSetAllowed.CodeA && currcs == CodeSet.CodeA)
|| (csa == CodeSetAllowed.CodeB && currcs == CodeSet.CodeB);
}
/// <summary>
/// Gets the integer code128 code value for a character (assuming the appropriate code set)
/// </summary>
/// <param name="CharAscii">character to convert</param>
/// <returns>code128 symbol value for the character</returns>
public static int CodeValueForChar(int CharAscii)
{
return (CharAscii >= 32) ? CharAscii - 32 : CharAscii + 64;
}
/// <summary>
/// Return the appropriate START code depending on the codeset we want to be in
/// </summary>
/// <param name="cs">The codeset you want to start in</param>
/// <returns>The code128 code to start a barcode in that codeset</returns>
public static int StartCodeForCodeSet(CodeSet cs)
{
return cs == CodeSet.CodeA ? cSTARTA : cSTARTB;
}
/// <summary>
/// Return the Code128 stop code
/// </summary>
/// <returns>the stop code</returns>
public static int StopCode()
{
return cSTOP;
}
/// <summary>
/// Indicates which code sets can represent a character -- CodeA, CodeB, or either
/// </summary>
public enum CodeSetAllowed
{
CodeA,
CodeB,
CodeAorB
}
}
}

Related

How to build the heliocentric algorithm?

Given this problem:
Consider two of the planets in the orbital system: Earth and Mars.
Assume the Earth orbits the Sun in exactly 365 Earth days, and Mars
orbits the Sun in exactly 687 Earth days. Thus the Earth’s orbit
starts at day 0 and continues to day 364, and then starts over at day
0. Mars orbits similarly, but on a 687-day time scale.
We would like to find out how long it will take until both planets are
on day. 0 of their orbits simultaneously. Write a program that can
determine this.
Input Format:
The first line of input contains an integer N indicating the number of
test cases. N lines follow. Each test case contains two integers E and
M. These indicate which days Earth and Mars are at their respective
orbits.
Output Format:
For each case, display the case number followed by the smallest number
of days until the two planets will both be on day 0 of their orbits.
Follow the format of the sample output.
Sample Input 1
0 0
364 686
360 682
0 1
1 0
Sample Output 1
Case 1: 0
Case 2: 1
Case 3: 5
Case 4: 239075
Case 5: 11679
I tried solving the problem using modules but it doesn't seem correct
static string readInput;
static string firstStr = "";
static string secondStr = "";
static int firstInput;
static int secondInput;
static int testCases = 10;
static int caseNumber = 1;
static int outPut;
caseNumber <= testCases
static void Main(string[] args) {
//recall runProcess as long caseNumber is less or equal testCases
while (caseNumber <= testCases) {
runProcess();
Console.WriteLine("Case " + caseNumber + ": " + outPut);
caseNumber++;
}
}
Read input from console:
/// <summary>
/// This is the main process, is extracted to void so we can recall it.
/// </summary>
public static void runProcess() {
readInput = Console.ReadLine();
if (readInput != null) {
for (int i = 0; i < readInput.Length; i++) {
secondStr = secondStr + readInput[i];
if (readInput[i] == ' ') {
firstStr = secondStr;
secondStr = "";
continue;
}
}
}
firstInput = Convert.ToInt32(firstStr);
secondInput = Convert.ToInt32(secondStr);
outPut = atZero(firstInput, secondInput);
}
/// <summary>
/// This method takes the input data from the console to later determine the zero point
/// </summary>
/// <param name="earthDays"></param>
/// <param name="marsDays"></param>
/// <returns></returns>
public static int atZero(int earthDays, int marsDays) {
int earthOrbit = 365;
int marsOrbit = 687;
int modEarth = earthOrbit;
int modMars = marsOrbit;
int earthDistinction = earthOrbit - earthDays;
int marsDistinction = marsOrbit - marsDays;
if ((modInverse(earthDistinction, marsDistinction, modMars)) == 0) {
return (modInverse(marsDistinction, earthDistinction, modEarth)) * marsDistinction;
} else {
return (modInverse(earthDistinction, marsDistinction, modMars)) * earthDistinction;
}
}
mod invert
/// <summary>
/// The method below takes a denominator, numerator and a mod to later invert the mod.
/// </summary>
/// <param name="denominator"></param>
/// <param name="numerator"></param>
/// <param name="mod"></param>
/// <returns>modInverse</returns>
static int modInverse(int denominator, int numerator, int mod) {
int i = mod, outputAll = 0, d = numerator;
while (denominator > 0) {
int divided = i / denominator, x = denominator;
denominator = i % x;
i = x;
x = d;
d = outputAll - divided * x;
outputAll = x;
}
outputAll %= mod;
if (outputAll < 0) outputAll = (outputAll + mod) % mod;
return outputAll;
}
Is there any way to solve the problem without modules?
Thanks.
A straight forward way to calculate a solution could be this method:
private static int DaysTillBothAt0(int currentEarthDay, int currentMarsDay)
{
int result = 0, earth = currentEarthDay, mars = currentMarsDay;
while (earth != 0 || mars != 0)
{
result += 1;
earth = (earth + 1) % 365;
mars = (mars + 1) % 687;
}
return result;
}
This is of course not the fastest alogrithm or mathematically extraordinary elegant, but for the required data range performance doesn't matter here at all. (I don't know what your teacher expects, though).
It simply counts the orbits forward until they meet at 0.
You can use this for your test cases like this:
result = DaysTillBothAt0(0, 0); // 0
result = DaysTillBothAt0(364, 686); // 1
result = DaysTillBothAt0(360, 682); // 5
result = DaysTillBothAt0(0, 1); // 239075
result = DaysTillBothAt0(1, 0); // 11679
One more solution for this problem
private static int DaysTillBothAt0(int currentEarthday, int currentMarsday) {
int count = 365 - currentEarthday;
currentMarsday = (currentMarsday + count) % 687;
while (currentMarsday != 0) {
currentMarsday = (currentMarsday + 365) % 687;
count += 365;
}
return currentMarsday;
}

Calculate FFT from SampleGrabber using DirectShow .NET

I'm developing a project using DirectShow .NET.
I'm trying to integrate a library called "WPF Sound Visualization Library" which creates a spectrum analyzer visual.
In order for the visual to work I need to implement these 2 methods in my player:
GetFFTData(float[] fftDataBuffer) - Assigns current FFT data to a buffer.
Remarks: The FFT data in the buffer should consist only of the real number intensity values. This means that if your FFT algorithm returns complex numbers (as many do), you'd run an algorithm similar to: for(int i = 0; i < complexNumbers.Length / 2; i++) fftResult[i] = Math.Sqrt(complexNumbers[i].Real * complexNumbers[i].Real + complexNumbers[i].Imaginary * complexNumbers[i].Imaginary);
GetFFTFrequencyIndex(int frequency) - Gets the index in the FFT data buffer for a given frequency.
Edit:
I already added the SampleGrabber and integrated it's callback with the GetFFTData (which is still not tested). But how do integrate the GetFFTFrequencyIndex method?
protected int SampleCB(double SampleTime, IMediaSample pSample)
{
IntPtr pointer = IntPtr.Zero;
pSample.GetPointer(out pointer);
sampleDataBytes = new byte[pSample.GetSize()];
Marshal.Copy(pointer, sampleDataBytes, 0, sampleDataBytes.Length);
var sampleTime = SampleTime;
var actualDataLength = pSample.GetActualDataLength();
/* Release unmanaged resources */
Marshal.ReleaseComObject(pSample);
pSample = null;
return (int)HResults.S_OK;
}
#region ISpectrumPlayer
byte[] sampleDataBytes = null;
public bool GetFFTData(float[] fftDataBuffer)
{
if (sampleDataBytes != null)
{
var sampleData = Utils.GetInt16Array(sampleDataBytes);
double[] pRealIn = new double[sampleData.Length];
for (var i = 0; i <= sampleData.Length - 1; i++)
pRealIn[i] = sampleData[i];
var pImagIn = new double[sampleDataBytes.Length];
var pRealOut = new double[sampleDataBytes.Length];
var pImagOut = new double[sampleDataBytes.Length];
FFTUtils.Compute((uint) pRealIn.Length, pRealIn, pImagIn, pRealOut, pImagOut, false);
fftDataBuffer = new float[sampleDataBytes.Length];
for (int i = 0; i < pRealOut.Length; i++)
fftDataBuffer[i] = (float) Math.Sqrt(pRealOut[i] * pRealOut[i] + pImagOut[i] * pImagOut[i]);
}
return true;
}
public int GetFFTFrequencyIndex(int frequency)
{
throw new NotImplementedException();
}
#endregion
I ודקג this class with methods that can help:
public class FFTUtils
{
public const Double DDC_PI = 3.14159265358979323846;
/// <summary>
/// Verifies a number is a power of two
/// </summary>
/// <param name="x">Number to check</param>
/// <returns>true if number is a power two (i.e.:1,2,4,8,16,...)</returns>
public static Boolean IsPowerOfTwo(UInt32 x)
{
return ((x != 0) && (x & (x - 1)) == 0);
}
/// <summary>
/// Get Next power of number.
/// </summary>
/// <param name="x">Number to check</param>
/// <returns>A power of two number</returns>
public static UInt32 NextPowerOfTwo(UInt32 x)
{
x = x - 1;
x = x | (x >> 1);
x = x | (x >> 2);
x = x | (x >> 4);
x = x | (x >> 8);
x = x | (x >> 16);
return x + 1;
}
/// <summary>
/// Get Number of bits needed for a power of two
/// </summary>
/// <param name="PowerOfTwo">Power of two number</param>
/// <returns>Number of bits</returns>
public static UInt32 NumberOfBitsNeeded(UInt32 PowerOfTwo)
{
if (PowerOfTwo > 0)
{
for (UInt32 i = 0, mask = 1; ; i++, mask <<= 1)
{
if ((PowerOfTwo & mask) != 0)
return i;
}
}
return 0; // error
}
/// <summary>
/// Reverse bits
/// </summary>
/// <param name="index">Bits</param>
/// <param name="NumBits">Number of bits to reverse</param>
/// <returns>Reverse Bits</returns>
public static UInt32 ReverseBits(UInt32 index, UInt32 NumBits)
{
UInt32 i, rev;
for (i = rev = 0; i < NumBits; i++)
{
rev = (rev << 1) | (index & 1);
index >>= 1;
}
return rev;
}
/// <summary>
/// Return index to frequency based on number of samples
/// </summary>
/// <param name="Index">sample index</param>
/// <param name="NumSamples">number of samples</param>
/// <returns>Frequency index range</returns>
public static Double IndexToFrequency(UInt32 Index, UInt32 NumSamples)
{
if (Index >= NumSamples)
return 0.0;
else if (Index <= NumSamples / 2)
return (double)Index / (double)NumSamples;
return -(double)(NumSamples - Index) / (double)NumSamples;
}
/// <summary>
/// Compute FFT
/// </summary>
/// <param name="NumSamples">NumSamples Number of samples (must be power two)</param>
/// <param name="pRealIn">Real samples</param>
/// <param name="pImagIn">Imaginary (optional, may be null)</param>
/// <param name="pRealOut">Real coefficient output</param>
/// <param name="pImagOut">Imaginary coefficient output</param>
/// <param name="bInverseTransform">bInverseTransform when true, compute Inverse FFT</param>
public static void Compute(UInt32 NumSamples, Double[] pRealIn, Double[] pImagIn,
Double[] pRealOut, Double[] pImagOut, Boolean bInverseTransform)
{
UInt32 NumBits; /* Number of bits needed to store indices */
UInt32 i, j, k, n;
UInt32 BlockSize, BlockEnd;
double angle_numerator = 2.0 * DDC_PI;
double tr, ti; /* temp real, temp imaginary */
if (pRealIn == null || pRealOut == null || pImagOut == null)
{
// error
throw new ArgumentNullException("Null argument");
}
if (!IsPowerOfTwo(NumSamples))
{
// error
throw new ArgumentException("Number of samples must be power of 2");
}
if (pRealIn.Length < NumSamples || (pImagIn != null && pImagIn.Length < NumSamples) ||
pRealOut.Length < NumSamples || pImagOut.Length < NumSamples)
{
// error
throw new ArgumentException("Invalid Array argument detected");
}
if (bInverseTransform)
angle_numerator = -angle_numerator;
NumBits = NumberOfBitsNeeded(NumSamples);
/*
** Do simultaneous data copy and bit-reversal ordering into outputs...
*/
for (i = 0; i < NumSamples; i++)
{
j = ReverseBits(i, NumBits);
pRealOut[j] = pRealIn[i];
pImagOut[j] = (double)((pImagIn == null) ? 0.0 : pImagIn[i]);
}
/*
** Do the FFT itself...
*/
BlockEnd = 1;
for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1)
{
double delta_angle = angle_numerator / (double)BlockSize;
double sm2 = Math.Sin(-2 * delta_angle);
double sm1 = Math.Sin(-delta_angle);
double cm2 = Math.Cos(-2 * delta_angle);
double cm1 = Math.Cos(-delta_angle);
double w = 2 * cm1;
double ar0, ar1, ar2;
double ai0, ai1, ai2;
for (i = 0; i < NumSamples; i += BlockSize)
{
ar2 = cm2;
ar1 = cm1;
ai2 = sm2;
ai1 = sm1;
for (j = i, n = 0; n < BlockEnd; j++, n++)
{
ar0 = w * ar1 - ar2;
ar2 = ar1;
ar1 = ar0;
ai0 = w * ai1 - ai2;
ai2 = ai1;
ai1 = ai0;
k = j + BlockEnd;
tr = ar0 * pRealOut[k] - ai0 * pImagOut[k];
ti = ar0 * pImagOut[k] + ai0 * pRealOut[k];
pRealOut[k] = (pRealOut[j] - tr);
pImagOut[k] = (pImagOut[j] - ti);
pRealOut[j] += (tr);
pImagOut[j] += (ti);
}
}
BlockEnd = BlockSize;
}
/*
** Need to normalize if inverse transform...
*/
if (bInverseTransform)
{
double denom = (double)(NumSamples);
for (i = 0; i < NumSamples; i++)
{
pRealOut[i] /= denom;
pImagOut[i] /= denom;
}
}
}
/// <summary>
/// Calculate normal (power spectrum)
/// </summary>
/// <param name="NumSamples">Number of sample</param>
/// <param name="pReal">Real coefficient buffer</param>
/// <param name="pImag">Imaginary coefficient buffer</param>
/// <param name="pAmpl">Working buffer to hold amplitude Xps(m) = | X(m)^2 | = Xreal(m)^2 + Ximag(m)^2</param>
public static void Norm(UInt32 NumSamples, Double[] pReal, Double[] pImag, Double[] pAmpl)
{
if (pReal == null || pImag == null || pAmpl == null)
{
// error
throw new ArgumentNullException("pReal,pImag,pAmpl");
}
if (pReal.Length < NumSamples || pImag.Length < NumSamples || pAmpl.Length < NumSamples)
{
// error
throw new ArgumentException("Invalid Array argument detected");
}
// Calculate amplitude values in the buffer provided
for (UInt32 i = 0; i < NumSamples; i++)
{
pAmpl[i] = pReal[i] * pReal[i] + pImag[i] * pImag[i];
}
}
/// <summary>
/// Find Peak frequency in Hz
/// </summary>
/// <param name="NumSamples">Number of samples</param>
/// <param name="pAmpl">Current amplitude</param>
/// <param name="samplingRate">Sampling rate in samples/second (Hz)</param>
/// <param name="index">Frequency index</param>
/// <returns>Peak frequency in Hz</returns>
public static Double PeakFrequency(UInt32 NumSamples, Double[] pAmpl, Double samplingRate, ref UInt32 index)
{
UInt32 N = NumSamples >> 1; // number of positive frequencies. (numSamples/2)
if (pAmpl == null)
{
// error
throw new ArgumentNullException("pAmpl");
}
if (pAmpl.Length < NumSamples)
{
// error
throw new ArgumentException("Invalid Array argument detected");
}
double maxAmpl = -1.0;
double peakFreq = -1.0;
index = 0;
for (UInt32 i = 0; i < N; i++)
{
if (pAmpl[i] > maxAmpl)
{
maxAmpl = (double)pAmpl[i];
index = i;
peakFreq = (double)(i);
}
}
return samplingRate * peakFreq / (double)(NumSamples);
}
}
Thank you so much!
If I remember well, the algorithm takes a real (e.g. int[n]) signal or a complex one (e.g. int[n][2]) and returns a complex FFT result.
So, it seems quite easy:
You take your input values (that you can plot as value-to-time in a chart, e.g. the left speaker audio values) and you feed them in the pRealIn parameter. In pImagIn you put zeros (as many as in pRealIn). In bInverseTransform you put false (of course).
Then you will take the result back in pRealOut & pImagOut. The result buffers should logically be of the same size as the input buffers.
You must take those two output buffers and combine them in pair like so (for each element of the OUT arrays):
fftDataBuffer[k] = Math.Sqrt(pRealOut[k] * pRealOut[k] + pImagOut[k] * pImagOut[k]); // Do this from 1 to n
FFT result is an array of complex values (x = real part and y = imaginary part - you can depict it on a Cartesian system as a vector). You want the vector's size/amplitude that why you do the above.
That is for GetFFTData.
I see that you have a function called IndexToFrequency. So that may work.
All you have to do is call this method for every index of your buffers. That is:
for(int i=0; i<n; i++) freq[i] = IndexToFrequency(i, n);
Keep those values stored and then in your GetFFTFrequencyIndex(int frequency) you find the closest match of the input parameter (frequency) to the elements in freq[n] and return its index.
I think that will be enough.
Important: Make sure that your buffers have a power-of-two size (NextPowerOfTwo seems to be designed to help you do just that).
If your data happens to be smaller some times, you can pad the values with zeros at the end (a.k.a. append zeros to your input buffers).
Also: To get a better resolution you can again pad with zeros your data. This will increase the 'smoothness' of your result which may be desirable.
Where did you find this code, if I may ask (just curious :) )?
So, that's all it! :)

Implementing Luhn algorithm using C#

I am using following code to implement Luhn algorithm for credit card check in C# language, but could not get the output to generate the check sum its showing validity. Kindly help me. Thank you in advance.
public class Program
{
private static void Main(string[]creditcard)
{
int sum = 0, d;
string num ="7992739871";
int a = 0;
for (int i = num.Length - 2; i >= 0; i--)
{
d = Convert.ToInt32(num.Substring(i, 1));
if (a % 2 == 0)
d = d * 2;
if (d > 9)
d -= 9;
sum += d;
a++;
}
if ((10 - (sum % 10) == Convert.ToInt32(num.Substring(num.Length - 1))))
Console.WriteLine("valid");
Console.WriteLine("sum of digits of the number" + sum);
}
}
Here are some extension methods that compute a Luhn checkdigit, validate a number with a checkdigit, and add a checkdigit to a number. Tested in .NET 4.5.
There are extension methods for strings, ints, int64s and IList.
I got some ideas for this from rosettacode.org
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
public static class CheckDigitExtension
{
static readonly int[] Results = { 0, 2, 4, 6, 8, 1, 3, 5, 7, 9 };
#region extension methods for IList<int>
/// <summary>
/// For a list of digits, compute the ending checkdigit
/// </summary>
/// <param name="digits">The list of digits for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static int CheckDigit(this IList<int> digits)
{
var i = 0;
var lengthMod = digits.Count%2;
return (digits.Sum(d => i++ % 2 == lengthMod ? d : Results[d]) * 9) % 10;
}
/// <summary>
/// Return a list of digits including the checkdigit
/// </summary>
/// <param name="digits">The original list of digits</param>
/// <returns>the new list of digits including checkdigit</returns>
public static IList<int> AppendCheckDigit(this IList<int> digits)
{
var result = digits;
result.Add(digits.CheckDigit());
return result;
}
/// <summary>
/// Returns true when a list of digits has a valid checkdigit
/// </summary>
/// <param name="digits">The list of digits to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this IList<int> digits)
{
return digits.Last() == CheckDigit(digits.Take(digits.Count - 1).ToList());
}
#endregion extension methods for IList<int>
#region extension methods for strings
/// <summary>
/// Internal conversion function to convert string into a list of ints
/// </summary>
/// <param name="digits">the original string</param>
/// <returns>the list of ints</returns>
private static IList<int> ToDigitList(this string digits)
{
return digits.Select(d => d - 48).ToList();
}
/// <summary>
/// For a string of digits, compute the ending checkdigit
/// </summary>
/// <param name="digits">The string of digits for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static string CheckDigit(this string digits)
{
return digits.ToDigitList().CheckDigit().ToString(CultureInfo.InvariantCulture);
}
/// <summary>
/// Return a string of digits including the checkdigit
/// </summary>
/// <param name="digits">The original string of digits</param>
/// <returns>the new string of digits including checkdigit</returns>
public static string AppendCheckDigit(this string digits)
{
return digits + digits.CheckDigit();
}
/// <summary>
/// Returns true when a string of digits has a valid checkdigit
/// </summary>
/// <param name="digits">The string of digits to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this string digits)
{
return digits.ToDigitList().HasValidCheckDigit();
}
#endregion extension methods for strings
#region extension methods for integers
/// <summary>
/// Internal conversion function to convert int into a list of ints, one for each digit
/// </summary>
/// <param name="digits">the original int</param>
/// <returns>the list of ints</returns>
private static IList<int> ToDigitList(this int digits)
{
return digits.ToString(CultureInfo.InvariantCulture).Select(d => d - 48).ToList();
}
/// <summary>
/// For an integer, compute the ending checkdigit
/// </summary>
/// <param name="digits">The integer for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static int CheckDigit(this int digits)
{
return digits.ToDigitList().CheckDigit();
}
/// <summary>
/// Return an integer including the checkdigit
/// </summary>
/// <param name="digits">The original integer</param>
/// <returns>the new integer including checkdigit</returns>
public static int AppendCheckDigit(this int digits)
{
return digits * 10 + digits.CheckDigit();
}
/// <summary>
/// Returns true when an integer has a valid checkdigit
/// </summary>
/// <param name="digits">The integer to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this int digits)
{
return digits.ToDigitList().HasValidCheckDigit();
}
#endregion extension methods for integers
#region extension methods for int64s
/// <summary>
/// Internal conversion function to convert int into a list of ints, one for each digit
/// </summary>
/// <param name="digits">the original int</param>
/// <returns>the list of ints</returns>
private static IList<int> ToDigitList(this Int64 digits)
{
return digits.ToString(CultureInfo.InvariantCulture).Select(d => d - 48).ToList();
}
/// <summary>
/// For an integer, compute the ending checkdigit
/// </summary>
/// <param name="digits">The integer for which to compute the check digit</param>
/// <returns>the check digit</returns>
public static int CheckDigit(this Int64 digits)
{
return digits.ToDigitList().CheckDigit();
}
/// <summary>
/// Return an integer including the checkdigit
/// </summary>
/// <param name="digits">The original integer</param>
/// <returns>the new integer including checkdigit</returns>
public static Int64 AppendCheckDigit(this Int64 digits)
{
return digits * 10 + digits.CheckDigit();
}
/// <summary>
/// Returns true when an integer has a valid checkdigit
/// </summary>
/// <param name="digits">The integer to check</param>
/// <returns>true/false depending on valid checkdigit</returns>
public static bool HasValidCheckDigit(this Int64 digits)
{
return digits.ToDigitList().HasValidCheckDigit();
}
#endregion extension methods for int64s
}
Here are some XUnit test cases that show how the extension methods work.
public class CheckDigitExtensionShould
{
[Fact]
public void ComputeCheckDigits()
{
Assert.Equal(0, (new List<int> { 0 }).CheckDigit());
Assert.Equal(8, (new List<int> { 1 }).CheckDigit());
Assert.Equal(6, (new List<int> { 2 }).CheckDigit());
Assert.Equal(0, (new List<int> { 3, 6, 1, 5, 5 }).CheckDigit());
Assert.Equal(0, 36155.CheckDigit());
Assert.Equal(8, (new List<int> { 3, 6, 1, 5, 6 }).CheckDigit());
Assert.Equal(8, 36156.CheckDigit());
Assert.Equal(6, 36157.CheckDigit());
Assert.Equal("6", "36157".CheckDigit());
Assert.Equal("3", "7992739871".CheckDigit());
}
[Fact]
public void ValidateCheckDigits()
{
Assert.True((new List<int> { 3, 6, 1, 5, 6, 8 }).HasValidCheckDigit());
Assert.True(361568.HasValidCheckDigit());
Assert.True("361568".HasValidCheckDigit());
Assert.True("79927398713".HasValidCheckDigit());
}
[Fact]
public void AppendCheckDigits()
{
Console.WriteLine("36156".CheckDigit());
Console.WriteLine("36156".AppendCheckDigit());
Assert.Equal("361568", "36156".AppendCheckDigit());
Assert.Equal("79927398713", "7992739871".AppendCheckDigit());
}
}
Compact Luhn check:
public static bool Luhn(string digits)
{
return digits.All(char.IsDigit) && digits.Reverse()
.Select(c => c - 48)
.Select((thisNum, i) => i % 2 == 0
? thisNum
:((thisNum *= 2) > 9 ? thisNum - 9 : thisNum)
).Sum() % 10 == 0;
}
Fiddle: https://dotnetfiddle.net/CCwE48
Here is a correct and fast implementation:
bool PassesLuhnCheck(string value)
{
long sum = 0;
for (int i = 0; i < value.Length; i++)
{
var digit = value[value.Length - 1 - i] - '0';
sum += (i % 2 != 0) ? GetDouble(digit) : digit;
}
return sum % 10 == 0;
int GetDouble(long i)
{
switch (i)
{
case 0: return 0;
case 1: return 2;
case 2: return 4;
case 3: return 6;
case 4: return 8;
case 5: return 1;
case 6: return 3;
case 7: return 5;
case 8: return 7;
case 9: return 9;
default: return 0;
}
}
}
I have tried this code which might help for other future folk:
public string GenerateLuhnNumber(string baseNumber)
{
if (!double.TryParse(baseNumber, out double baseNumberInt))
throw new InvalidWorkflowException($"Field contains non-numeric character(s) : {baseNumber}");
var step2 = string.Empty;
for (var index = baseNumber.Length - 1; index >= 0; index -= 2)
{
var doubleTheValue = (int.Parse(baseNumber[index].ToString())) * 2;
if (doubleTheValue > 9)
doubleTheValue = Math.Abs(doubleTheValue).ToString().Sum(c => Convert.ToInt32(c.ToString()));
step2 = step2.Insert(0, (index != 0 ? baseNumber[index - 1].ToString() : "") + doubleTheValue);
}
var step3 = Math.Abs(Convert.ToDouble(step2)).ToString(CultureInfo.InvariantCulture).Sum(c => Convert.ToDouble(c.ToString())).ToString(CultureInfo.InvariantCulture);
var lastDigitStep3 = Convert.ToInt32(step3[step3.Length - 1].ToString());
string checkDigit = "0";
if (lastDigitStep3 != 0)
checkDigit = (10 - lastDigitStep3).ToString();
return baseNumber + checkDigit;
}
You can do it very simply (reference),
public static bool Mod10Check(string creditCardNumber)
{
// check whether input string is null or empty
if (string.IsNullOrEmpty(creditCardNumber))
{
return false;
}
int sumOfDigits = creditCardNumber.Where((e) => e >= '0' && e <= '9')
.Reverse()
.Select((e, i) => ((int)e - 48) * (i % 2 == 0 ? 1 : 2))
.Sum((e) => e / 10 + e % 10);
return sumOfDigits % 10 == 0;
}
This one will do it I believe:
static void Main(string[] args)
{
string number = "1762483";
int digit = 0;
int sum = 0;
for (int i = 0; i <= number.Length - 1; i++)
{
if (i % 2 == 1)
{
digit = int.Parse(number.Substring(i, 1));
sum += DoubleDigitValue(digit);
Console.WriteLine(digit);
}
else
{
digit = int.Parse(number.Substring(i, 1));
sum += digit;
}
}
Console.WriteLine(sum);
if (sum % 10 == 0)
{
Console.WriteLine("valid");
}
else
{
Console.WriteLine("Invalid");
}
}
static int DoubleDigitValue(int digit)
{
int sum;
int doubledDigit = digit * 2;
if (doubledDigit >= 10)
{
sum = 1 + doubledDigit % 10;
} else
{
sum = doubledDigit;
}
return sum;
}
These are my methods for validating and calculating the last digit. To validate a number simply check that the result of the first method is 0;
private int LuhnChecksum(string input)
{
var length = input.Length;
var even = length % 2;
var sum = 0;
for (var i = length - 1; i >= 0; i--)
{
var d = int.Parse(input[i].ToString());
if (i % 2 == even)
d *= 2;
if (d > 9)
d -= 9;
sum += d;
}
return sum % 10;
}
private int LuhnCalculateLastDigit(string input)
{
var checksum = LuhnChecksum(input + "0");
return checksum == 0 ? 0 : 10 - checksum;
}
I just interprete code from C to C#. Code in C you can find there:(https://uk.wikipedia.org/wiki/%D0%90%D0%BB%D0%B3%D0%BE%D1%80%D0%B8%D1%82%D0%BC_%D0%9B%D1%83%D0%BD%D0%B0). I cheked it for a few device.
byte[] data = new byte[19];
//fill the data[]
...
//use it
if (checkByLuhn(data))
{
//check complete
}
...
private bool checkByLuhn(byte[] pPurposed)
{
int nSum = 0;
int nDigits = pPurposed.Length;
int nParity = (nDigits - 1) % 2;
char[] cDigit = new char[] { '0','\0' };
for (int i = nDigits; i > 0; i--)
{
cDigit[0] = (char)pPurposed[i - 1];
int nDigit = (int)Char.GetNumericValue(cDigit[0]);
if (nParity == i % 2)
{
nDigit = nDigit * 2;
}
nSum += nDigit / 10;
nSum += nDigit % 10;
}
return 0 == nSum % 10;
}
Philippe had an excellent answer, but here's a simpler version that is still O(n). I've tested it in xUnit with a dataset of 30 and it is factors faster than some of the upvoted answers.
public static bool CheckLuhnParity(string digits)
{
bool isValid = false;
if (!string.IsNullOrEmpty(digits))
{
long sum = 0;
int parity = digits.Length % 2;
for (int i = 0; i < digits.Length; i++)
{
int digit = digits[^(i + 1)] - '0';
sum += (i % 2 == parity) ? Luhn(digit) : digit;
}
isValid = (sum % 10) == 0;
}
return isValid;
int Luhn(int digit) => (digit *= 2) > 9 ? digit - 9 : digit;
}
This has the same flaw as the accepted answer, though; it doesn't fully implement the Luhn algorithm. It assumes that the actual check digit does not need to be verified which means invalid numbers may be accepted. Here's a better way:
public static bool CheckLuhnDigit(string digits)
{
bool isValid = false;
if (!string.IsNullOrEmpty(digits) && digits.Length > 2)
{
long sum = 0;
for (int i = 0; i < digits.Length - 1; i++)
{
int digit = digits[^(i + 2)] - '0';
sum += (i % 2 == 0) ? Luhn(digit) : digit;
}
int checkDigit = digits[^1] - '0';
isValid = (10 - (sum % 10)) % 10 == checkDigit;
}
return isValid;
int Luhn(int digit) => (digit *= 2) > 9 ? digit - 9 : digit;
}
Does anyone want to attempt O(log n)?
Here's shorter version to get checksum
private int getCheckSum(string number)
{
var sum = number.Reverse() //Reverse
.Select((d, i) => i % 2 == 0 ? Convert.ToInt32(d.ToString()) * 2 : Convert.ToInt32(d.ToString())) //double every 2nd digit including starting
.Select(x => x.ToString().Select(c => Convert.ToInt32(c.ToString())).Sum()) //sum double digit number 18 = 1 + 8 = 9
.Sum(); //Sum all
return (10 - (sum % 10)) % 10;
}
To validate a check sum, pass number without checksum and compare the result with last digit of original number .
Your algorithm is correct, but you're testing it wrong way.
I can see your sample input is from wiki page: Luhn algorithm. Difference is, they are calculating check digit for "7992739871X", where X is the check digit they're looking for. Your code validates number your already have!
Change your input to "79927398713" and it will mark it as correct number.
Update
OK, I see where is the problem. You're not taking this part of algorithm right:
From the rightmost digit, which is the check digit, moving left, double the value of every second digit;
Your code takes every other digit, but not necessary starting from most left digit. Try this code:
for (int i = 0; i < num.Length; i++)
{
d = Convert.ToInt32(num.Substring(num.Length - 1 - i, 1));
if (a % 2 == 0)
d = d * 2;
if (d > 9)
d -= 9;
sum += d;
a++;
}
var checkDigit = 10 - (sum % 10);

How to round a integer to the close hundred?

I don't know it my nomenclature is correct! Anyway, these are the integer I have, for example :
76
121
9660
And I'd like to round them to the close hundred, such as they must become :
100
100
9700
How can I do it faster in C#? I think about an algorithm, but maybe there are some utilities on C#?
Try the Math.Round method. Here's how:
Math.Round(76d / 100d, 0) * 100;
Math.Round(121d / 100d, 0) * 100;
Math.Round(9660d / 100d, 0) * 100;
I wrote a simple extension method to generalize this kind of rounding a while ago:
public static class MathExtensions
{
public static int Round(this int i, int nearest)
{
if (nearest <= 0 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException("nearest", "Must round to a positive multiple of 10");
return (i + 5 * nearest / 10) / nearest * nearest;
}
}
It leverages integer division to find the closest rounding.
Example use:
int example = 152;
Console.WriteLine(example.Round(100)); // round to the nearest 100
Console.WriteLine(example.Round(10)); // round to the nearest 10
And in your example:
Console.WriteLine(76.Round(100)); // 100
Console.WriteLine(121.Round(100)); // 100
Console.WriteLine(9660.Round(100)); // 9700
Try this expression:
(n + 50) / 100 * 100
Caveat: only works for non-negative n.
Just some addition to #krizzzn's accepted answer...
Do note that the following will return 0:
Math.Round(50d / 100d, 0) * 100;
Consider using the following and make it return 100 instead:
Math.Round(50d / 100d, 0, MidpointRounding.AwayFromZero) * 100;
Depending on what you're doing, using decimals might be a better choice (note the m):
Math.Round(50m / 100m, 0, MidpointRounding.AwayFromZero) * 100m;
I know this is an old thread. I wrote a new method. Hope this will be useful for some one.
public static double Round(this float value, int precision)
{
if (precision < -4 && precision > 15)
throw new ArgumentOutOfRangeException("precision", "Must be and integer between -4 and 15");
if (precision >= 0) return Math.Round(value, precision);
else
{
precision = (int)Math.Pow(10, Math.Abs(precision));
value = value + (5 * precision / 10);
return Math.Round(value - (value % precision), 0);
}
}
Example:
float value = 6666.677777F;
Console.Write(value.Round(2)); //6666.68
Console.Write(value.Round(0)); //6667
Console.Write(value.Round(-2)); //6700
Hi i write this extension this gets the next hundred for each number you pass
/// <summary>
/// this extension gets the next hunfìdred for any number you whant
/// </summary>
/// <param name="i">numeber to rounded</param>
/// <returns>the next hundred number</returns>
/// <remarks>
/// eg.:
/// i = 21 gets 100
/// i = 121 gets 200
/// i = 200 gets 300
/// i = 1211 gets 1300
/// i = -108 gets -200
/// </remarks>
public static int RoundToNextHundred(this int i)
{
return i += (100 * Math.Sign(i) - i % 100);
//use this line below if you want RoundHundred not NEXT
//return i % 100 == byte.MinValue? i : i += (100 * Math.Sign(i) - i % 100);
}
//and for answer at title point use this algoritm
var closeHundred = Math.Round(number / 100D)*100;
//and here the extension method if you prefer
/// <summary>
/// this extension gets the close hundred for any number you whant
/// </summary>
/// <param name="number">number to be rounded</param>
/// <returns>the close hundred number</returns>
/// <remarks>
/// eg.:
/// number = 21 gets 0
/// number = 149 gets 100
/// number = 151 gets 200
/// number = -149 gets -100
/// number = -151 gets -200
/// </remarks>
public static int RoundCloseHundred(this int number)
{
return (int)Math.Round(number / 100D) * 100;
}
If you only want to round integer numbers up (as the OP actually did), then you can resort to this solution:
public static class MathExtensions
{
public static int RoundUpTo(this int number, int nearest)
{
if (nearest < 10 || nearest % 10 != 0)
throw new ArgumentOutOfRangeException(nameof(nearest), $"{nameof(nearest)} must be a positive multiple of 10, but you specified {nearest}.");
int modulo = number % nearest;
return modulo == 0 ? number : modulo > 0 ? number + (nearest - modulo) : number - modulo;
}
}
If you want to perform floating-point (or decimal) rounding, then resort to the answers of #krizzzn and #Jim Aho.
int num = 9660;
int remainder = num % 100;
Console.WriteLine(remainder < 50 ? num - remainder : num + (100 -remainder));
Note: I haven't tested this thoroughly.
I had a similar project internally where the business requirements were to search within the 100's range of a given number and find duplicate DB records. So if the user was using line 856 I would search 800 - 899. If the user was using 8567 I would search 8500 - 8599. Not an exact rounding by 100's, but thought I would include my unique approach as some of these basic coding questions are embedded within a larger business project. To test this I seeded a decimal list from 1 - 99999 and spit the results out into a file.
/// <summary>
/// This method accepts an inbound Line Number and returns the line range
/// in the form of lowest to highest based on 100's
/// Example would be 9122 returns 9100 - 9199
/// It's used for generating some additional BOM Temp functionality.
/// </summary>
/// <param name="inboundNumber"></param>
/// <returns></returns>
public static ProjectLineRange CalculateLineRange(decimal inboundNumber)
{
var lineRange = new ProjectLineRange();
var numberLength = inboundNumber.ToString(CultureInfo.InvariantCulture).Length;
switch (numberLength)
{
case 0: //NULL?
break;
case 1: //Represents 1 - 9
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 2: //Represents 10 - 99
lineRange.LineBottom = 1;
lineRange.LineTop = 99;
break;
case 3: //Represents 100 - 999
lineRange = CalculateHundredsRange((int)(inboundNumber / 100));
break;
case 4: //Represents 1000 - 9999
lineRange = CalculateThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
case 5: //Represents 10000 - 99999
lineRange = CalculateTenThousandsRange(
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(2, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(1, 1)),
Convert.ToInt32(inboundNumber.ToString(CultureInfo.InvariantCulture).Substring(0, 1)));
break;
}
return lineRange;
}
public class ProjectLineRange
{
public decimal LineBottom { get; set; }
public decimal LineTop { get; set; }
}
/// <summary>
/// Helper method to return the range for the 100's place
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateHundredsRange(int hundredsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
tempLineRange.LineBottom = hundredsPlaceValue * 100;
tempLineRange.LineTop = tempLineRange.LineBottom + 99;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 1000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
/// <summary>
/// Helper method to return the range for the 100's place when factoring a 10000's number
/// </summary>
/// <param name="hundredsPlaceValue"></param>
/// <param name="thousandsPlaceValue"></param>
/// <param name="tenThousandsPlaceValue"></param>
/// <returns></returns>
public static ProjectLineRange CalculateTenThousandsRange(int hundredsPlaceValue, int thousandsPlaceValue, int tenThousandsPlaceValue)
{
var tempLineRange = new ProjectLineRange();
var tempThousands = thousandsPlaceValue * 1000;
var tempTenThousands = tenThousandsPlaceValue * 10000;
var hundredsRange = CalculateHundredsRange(hundredsPlaceValue);
tempLineRange.LineBottom = tempTenThousands + tempThousands + hundredsRange.LineBottom;
tempLineRange.LineTop = tempTenThousands + tempThousands + hundredsRange.LineTop;
return tempLineRange;
}
public static class Maths
{
public static int Round(this int value, int precision)
{
var coef = Math.Pow(10, Math.Abs(precision));
var x = (int)Math.Round(value / coef, 0);
return x * (int)coef;
}
}
var number = 34569;
Debug.WriteLine(number.Round(0));//34569
Debug.WriteLine(number.Round(1));//34570
Debug.WriteLine(number.Round(2));//34600
Debug.WriteLine(number.Round(3));//35000
Debug.WriteLine(number.Round(4));//30000
Debug.WriteLine(number.Round(5));// 0
Debug.WriteLine(number.Round(6));// 0

How to write a Linear Congruential Generator (LCG) in C#? Or are there any well known implementations?

I am wanting to generate a random array of sequences that repeat and only use each number once. For example, given a range of 0-9 with 2 different seeds you might get
Seed 1: 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4 | 7 3 5 9 0 8 1 2 6 4
Seed 2: 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0 | 2 5 7 1 4 9 6 8 3 0
From what I understand, a Linear Congruential Random Number Generator or LCRNG or LCG can give me this http://en.wikipedia.org/wiki/Linear_congruential_generator
Any idea if an implementation exists in C# or how I would get started with writing one.
How does a Mersenne Twister differ from an LCG?
Not sure all of my questions are answered, but here is what I ended up using. Because I am bounding the sample size to the range of values from max to min, I am selecting a different prime number that stays static as long as the same initial seed is given. I do this because I want the same sequence given the same seed and the same min/max bounds for repeatability of testing.
Please critique anything I do here, this is just what I came up with in a jiffy:
using System;
using System.Collections.Generic;
namespace FULLCYCLE
{
public class RandomNumber
{
private int _value;
private int _prime;
private static List<int> primes = new List<int>()
{
11,
23,
47,
97,
797,
1597,
6421,
25717,
51437,
102877,
411527,
823117,
1646237,
3292489,
6584983,
13169977,
26339969,
52679969,
105359939,
210719881,
421439783,
842879579,
1685759167
};
public RandomNumber( int seed )
{
_prime = primes[seed%primes.Count];
_value = seed;
}
public int Next( int min, int max )
{
int maxrate = (max-min+1);
if (_value > maxrate)
{
_value = _value % maxrate;
}
_value = (_value + _prime) % maxrate;
return _value + min;
}
}
}
Why not just use the existing Random class and a Knuth shuffle on your input sequence?
Regarding your edit, there are several problems with your LCG as a random number generator...
It can produce obvious patterns:
// generates 3, 4, 5, 6, 7, 8, 9, 0, 1, 2
var rng = new RandomNumber(42);
for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(0, 9));
It can repeat itself:
// generates 579, 579, 579, 579, 579, 579, 579, 579, 579, 579
var rng = new RandomNumber(123);
for (int i = 0; i < 10; i++) Console.WriteLine(rng.Next(456, 51892));
There are many other seed/min/max combinations that will generate problematic results.
Try the following code:
namespace System
{
/// <summary>
/// Represents a pseudo-random number generator using the linear congruential method:
/// X[i+1] = (a • X[i] + c) % m (where i is greater than or equal to 0).
/// </summary>
public class LinearCongruentialRandom : Random
{
private int _x = 1971111612;
private int _a = 2147483629;
private int _c = 2147483587;
private int _m = 2147483647;
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with default values.
/// </summary>
public LinearCongruentialRandom()
{
= base.Next(0, _m);
}
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with default values.
/// </summary>
public LinearCongruentialRandom(int seed)
{
if (seed >= _m) throw new ArgumentOutOfRangeException(nameof(seed), seed, null);
_x = seed;
}
/// <summary>
/// Initializes a new instance of <see cref="LinearCongruentialRandom"/> with the specified parameters.
/// </summary>
/// <param name="seed">Initial seed value less than m.</param>
/// <param name="a">A multiple of p for every prime p that is a divisor of m.</param>
/// <param name="c">Increment c. The numbers c and m must be relatively prime.</param>
/// <param name="m">The length of the repetition period m. The numbers c and m must be relatively prime.</param>
public LinearCongruentialRandom(int seed, int a, int c, int m) : this(seed)
{
_a = a;
_c=c;
_m=m;
}
/// <inheritdoc cref="Random.Next()"/>
public override int Next()
{
return _x = (_a * _x + _c) % _m;
}
/// <inheritdoc cref="Random.NextBytes(byte[])"/>
public override void NextBytes(byte[] buffer)
{
if (buffer == null)
throw new ArgumentNullException(nameof(buffer));
unchecked
{
for (int index = 0; index < buffer.Length; ++index)
buffer[index] = (byte)Next();
}
}
}
}

Categories