我有一个检查数字是否可以被11整除的方法。
public bool IsBankAccount(string BankNumber)
{
int factor = 9;
int restult = 0;
try
{
if ((BankNumber.Length == 9))
{
for (int i = 0; i < BankNumber.Length; i++)
{
restult += int.Parse(BankNumber.Substring(i, 1)) * factor;
factor -= 1;
}
return (restult % 11 == 0);
}
else
{
//Wrong length;
return false;
}
}
catch (Exception)
{
return false;
}
}
但如何生成所有第一个银行帐号,即第一个号码是:
100000002 =因为9 * 1 + 8 * 0 + 7 * 0 + 6 * 0 + 5 * 0 + 4 * 0 + 3 * 0 + 2 * 0 + 1 * 2 = 11
如果您想要所有银行帐号。这是一个9位数的1000万个数字。所以1000 000 000/11 = 90909090.9 11-11个数字
我只是尝试不同的解决方案。
但如果我试试这个:
static readonly int[] multipliers = {9, 8, 7, 6, 5, 4, 3, 2, 1};
static void Main(string[] args)
{
var bansAsStrings = BANS().Take(100).Select(ban => ban.ToString());
foreach (var ban in bansAsStrings)
{
Console.WriteLine(ban);
}
Console.ReadKey();
}
static IEnumerable<int> BANS()
{
int[] digits = { 1, 0, 0, 0, 0, 0, 0, 0, 2 };
int carryFlag = 0;
do
{
int sum = digits.Zip(multipliers, (d, m) => d * m)
.Sum();
if (sum % 11 == 0)
yield return sum;
int digitIndex = digits.Length - 1;
do
{
digits[8] += 1 + carryFlag;
if (digits[8] == 10)
{
digits[digitIndex--] = 0;
carryFlag = 1;
}
else
carryFlag = 0;
}
while (carryFlag == 1 && digitIndex >= 0);
}
while (carryFlag == 0);
yield break;
}
输出为11 100次。
我现在就这样:
static void Main(string[] args)
{
const int linesPerFile = 10;
const string destinationFileName = @"G:\Folder\File-Part-{0}.txt";
//string fileName = "File";
foreach (var bank in BankAcoutNumbers.BANS.Take(200))
{
var fileCounter = 0;
var destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
try
{
// foreach (var bank in BankAcoutNumbers.BANS.Take(100))
//{
var lineCounter = 0;
string line;
while ((line = destiNationFile.NewLine) != null )
{
if (lineCounter >= linesPerFile)
{
lineCounter = 0;
fileCounter++;
destiNationFile.Dispose();
destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
}
destiNationFile.WriteLine(bank);
lineCounter++;
}
//}
}
catch (Exception)
{
throw;
}
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
}
但现在每次写下第一个值:1000 000 02
我现在就这样:
static void Main(string [] args) {
const int linesPerFile = 10;
const string destinationFileName = @"G:\Folder\File-Part-{0}.txt";
//string fileName = "File";
var maxNumberOfFiles = 20;
var fileCounter = 0;
var destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
try
{
// foreach (var bank in BankAcoutNumbers.BANS.Take(100))
//{
var lineCounter = 0;
string line;
while (fileCounter < maxNumberOfFiles)
{
foreach (var bank in BankAcoutNumbers.BANS.Take(200))
{
if (lineCounter >= linesPerFile)
{
lineCounter = 0;
fileCounter++;
destiNationFile.Dispose();
destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
}
destiNationFile.WriteLine(bank);
lineCounter++;
}
fileCounter++;
//}
}
}
catch (Exception)
{
throw;
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
但我不喜欢你每次都要计算MaxFiles的数量。还有其他方法吗?感谢
以下是更新:
static void Main(string [] args) {
const int linesPerFile = 10;
string path = @"G:\Folder";
const string destinationFileName = @"G:\Folder\File-Part-{0}.txt";
//string fileName = "File";
var maxNumberOfFiles = 10;
Stopwatch timer = new Stopwatch();
var fileCounter = 0;
if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}
var destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
try
{
// foreach (var bank in BankAcoutNumbers.BANS.Take(100))
//{
var lineCounter = 0;
string line;
while (fileCounter <= maxNumberOfFiles)
{
timer.Start();
foreach (var bank in BankAcoutNumbers.BANS.Take(100))
{
if (lineCounter % linesPerFile == 0)
{
//lineCounter = 0;
destiNationFile.Flush();
destiNationFile.Dispose();
destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
fileCounter++;
}
destiNationFile.WriteLine(bank);
lineCounter++;
}
fileCounter++;
//}
}
timer.Stop();
// Console.WriteLine(BankAcoutNumbers.BANS.Count());
Console.WriteLine(timer.Elapsed.Seconds);
}
catch (Exception)
{
throw;
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
但要获取文件名,如下所示:Nr [文件中的第一个数字] - [文件中的最后一个数字] .txt谢谢
我现在就这样:
static void Main(string[] args)
{
const int linesPerFile = 10;
string path = @"G:\Folder";
const string destinationFileName = @"G:\Folder\File-Part-{0}.txt";
var bans = BankAcoutNumbers.BANS;
var counter = 100;
string tempFile;
//string fileName = "File";
var maxNumberOfFiles = 10;
Stopwatch timer = new Stopwatch();
var fileCounter = 0;
if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}
var destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
try
{
// foreach (var bank in BankAcoutNumbers.BANS.Take(100))
//{
var lineCounter = 0;
string line;
while (fileCounter <= maxNumberOfFiles)
{
timer.Start();
foreach (var bank in bans)
{
if (--counter == 0)
{
break;
}
if (lineCounter % linesPerFile == 0)
{
//lineCounter = 0;
destiNationFile.Flush();
destiNationFile.Dispose();
destiNationFile = new StreamWriter(string.Format(destinationFileName, fileCounter + 1));
fileCounter++;
}
destiNationFile.WriteLine(bank);
lineCounter++;
fileCounter++;
//}
}
}
timer.Stop();
// Console.WriteLine(BankAcoutNumbers.BANS.Count());
Console.WriteLine(timer.Elapsed.Seconds);
}
catch (Exception)
{
throw;
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
但是每次十个文件的最后一个文件都是空的。
如何获取文件名?
static void Main(string [] args) {
const int linesPerFile = 10;
string path = @"G:\Folder";
//string fileName = string.Format("{0}{1}-", part[0], part[part.Count - 1]);
var bans = BankAcoutNumbers.BANS;
string tempFile;
const int MAX_FILES = 10;
const int BANS_PER_FILE = 10;
int bansCounter = 0;
var part = new List<int>();
string fileName = string.Format("{0}-{1}", part[0], part[part.Count - 1]);
var maxNumberOfFiles = 10;
Stopwatch timer = new Stopwatch();
var fileCounter = 0;
if (!Directory.Exists(path))
{
DirectoryInfo di = Directory.CreateDirectory(path);
}
//var destiNationFile = new StreamWriter(string.Format(fileName, fileCounter + 1));
try
{
// foreach (var bank in BankAcoutNumbers.BANS.Take(100))
//{
var lineCounter = 0;
string line;
while (fileCounter <= maxNumberOfFiles)
{
timer.Start();
foreach (var bank in BankAcoutNumbers.BANS)
{
part.Add(bank);
if(++bansCounter >= BANS_PER_FILE)
{
//string fileName2 = string.Format("{0}-{1}", part[0], part[part.Count - 1]);
var destinationFile = new StreamWriter(fileName);
//destiNationFile = new StreamWriter(fileName);
Console.WriteLine("NR{0}", fileName);
foreach (var partBan in part )
Console.WriteLine(partBan);
part.Clear();
bansCounter = 0;
if (++fileCounter >= MAX_FILES)
break;
//lineCounter = 0;
//destiNationFile.Flush();
//destiNationFile.Dispose();
//destiNationFile = new StreamWriter(string.Format(fileName, fileCounter + 1));
//fileCounter++;
}
//destiNationFile.WriteLine(bank);
//lineCounter++;
}
//fileCounter++;
//}
}
timer.Stop();
// Console.WriteLine(BankAcoutNumbers.BANS.Count());
Console.WriteLine(timer.Elapsed.Seconds);
}
catch (Exception)
{
throw;
}
// Keep the console window open in debug mode.
System.Console.WriteLine("Press any key to exit.");
System.Console.ReadKey();
}
答案 0 :(得分:3)
public static IEnumerable<int> BANS
{
get
{
int[] digits = { 1, 0, 0, 0, 0, 0, 0, 0, 2 };
int carryFlag = 0;
do
{
int sum = digits.Select((d, i) => d * (9 - i))
.Sum();
if (sum % 11 == 0)
yield return digits.Aggregate(0, (accumulator, digit) => accumulator * 10 + digit);
int digitIndex = digits.Length - 1;
do
{
digits[digitIndex] += 1;
if (digits[digitIndex] == 10)
{
digits[digitIndex--] = 0;
carryFlag = 1;
}
else
carryFlag = 0;
}
while (digitIndex >= 0 && carryFlag == 1);
}
while (carryFlag == 0);
yield break;
}
}
Console.WriteLine(BANS.Count())
给了81818182 BAN。虚拟机中的计算时间约为5分钟。
前10个值是:
foreach (var ban in BANS.Take(10))
Console.WriteLine(ban);
----------------------------------
100000002
100000010
100000029
100000037
100000045
100000053
100000061
100000088
100000096
100000118
关于第二个问题:
static void Main(string[] args)
{
const int MAX_FILES = 10;
const int BANS_PER_FILE = 10;
int filesCounter = 0;
int bansCounter = 0;
var part = new List<int>();
foreach (var ban in BANS)
{
part.Add(ban);
if (++bansCounter >= BANS_PER_FILE)
{
string fileName = string.Format("{0}-{1}.txt", part[0], part[part.Count - 1]);
Console.WriteLine("Filename '{0}'", fileName);
foreach (var partBan in part)
Console.WriteLine(partBan);
part.Clear();
bansCounter = 0;
if (++filesCounter >= MAX_FILES)
break;
}
}
}
答案 1 :(得分:0)
这是你想要的吗?
var bankAccounts = new List<string>(100);
for(long i = 100000000; bankAccounts.Count < 100;i++)
{
var stringNumber = i.ToString();
if (IsBankAccount(stringNumber))
bankAccounts.Add(stringNumber);
}
这也可以通过LINQ完成,如下所示。
var accounts = Enumerable.Range(100000000, 2000) // 2000 is a guess, there's sure 100 values divisible by 11 in that range
.Select(n => n.ToString())
.Where(IsBankAccount)
.Take(100)
.ToList();
由于银行帐户中只有数字,因此您可以在没有字符串转换和字符串操作的情况下执行此操作。
要获取所有这些内容,请将2000替换为899999999,但即使您执行.AsParallel()
也需要很长时间才能完成,因为该算法确实无效。
基于ie的评论,快速算法可能看起来像这样,但它仍然非常耗费内存。
var nums = new List<string>();
for (int i = 100000002; i < 1000000000; i += 11)
nums.Add(i.ToString());
答案 2 :(得分:0)
您可以通过计算最后一位数作为校验位来枚举可能的数字:
static void Main(string[] args)
{
foreach (var num in GetMod11Sequence(10000000, 100000000).Take(100))
{
if (!CheckMod11CheckChar(num))
{
throw new InvalidOperationException();
}
else
{
Console.WriteLine(num);
}
}
}
private static IEnumerable<string> GetMod11Sequence(int start, int stop)
{
//Contract.Requires(start > 0);
//Contract.Requires(stop > start);
//Contract.Requires(stop < 1000000000);
for (int c = start; c < stop; c++)
{
string number = c.ToString();
char check;
if (TryCalculateMod11CheckChar(number, out check))
{
yield return number + check;
}
}
}
private static bool CheckMod11CheckChar(string number)
{
//Contract.Requires(number != null);
//Contract.Requires(number.All(c => char.IsDigit(c)));
int factor = number.Length;
int sum = 0;
for (int i = 0; i < number.Length; i++)
{
int cval = number[i] - '0';
sum += cval * factor;
factor--;
}
return sum % 11 == 0;
}
private static bool TryCalculateMod11CheckChar(string number, out char checkDigit)
{
//Contract.Requires(number != null);
int factor = number.Length + 1;
int sum = 0;
for (int i = 0; i < number.Length; i++)
{
int cval = number[i] - '0';
sum += cval * factor;
factor--;
}
//Contract.Assert(factor == 1);
int delta = sum % 11;
if (delta == 1)
{
// I cannot add 10, so this number is unavailable
checkDigit = '!';
return false;
}
else
{
if (delta == 0)
{
checkDigit = '0';
}
else
{
checkDigit = (11 - delta).ToString()[0];
}
return true;
}
}