问题:带进位规则的打表计数器,由显示的数求出其真实的值,规则是每经过4就加1,例如从1开始计数,计数到4的时候直接跳成了5,到14的时候直接跳成了15,到24的时候直接跳成25。。。。到40的时候跳成了50,以此类推,因此如果显示的数为100,那么实际减去跳过的数,就是81
算法主要思想:利用对数方法确定显示数的数量级进行逐级求位差提高算法时间效率(100,1000这种特殊数,另外-1,化1为9,结果不变的同时利于位差存在性标志系数的判断)
C# 代码实现:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace 缝4添1还原真实数算法
{
class Program
{
static System.DateTime currentTime1 = new System.DateTime();
static System.DateTime currentTime2 = new System.DateTime();
/***
需要的变量参数:
1、待计算值x
2、计算结果(进位得出的差值)difference
3、待计算值的十进制最高位的位数top_digit
4、该数的数量级,times1 = x / top_digit(例如10e3)
5、十进制数的阶数(也表示该数的数量级,lg(times1))
***/
static public int x, difference, top_digit, times1, times2;
List<int> Digits = new List<int>();//十进制位数存储序列,Digits[0]为第lg(x / top_digit) == 0位,Digits[1]为第lg(x / top_digit) == 1位,以此类推
public void real(int x)
{
//获取最高位的值
if (x / 10 != 0)
{
top_digit = x;
do
{
top_digit = top_digit / 10;
}
while (top_digit >= 10);
}
else
{
top_digit = x;
}
times1 = x / top_digit;
times2 = Convert.ToInt32(Math.Log10(Convert.ToDouble(times1)));//十进制数的阶数
difference = different_find(times2 , x);
}
public int different_find(int times2, int x) //获取进位差值
{
int num = x;
Digits.Add(num % 10);//生成十进制数的lg(digit_now * 10eN)==0位数字序列
int different_result = 0;//总位差运算结果
int different_SameOrder = 0;//同阶位差运算结果
int different_ReducedOrder = 0;//降阶位差运算结果
int SameOrder_change;//同阶位差存在性标志系数
int a;
//获取Digits序列
for (int i = 0; i < times2; i++)
{
num = num / 10;
Digits.Add(num % 10);//生成十进制数的位序列(从lg(digit_now * 10eN)==1位开始计算)
}
for (int j = 0; j < Digits.Count; j++)//j为求进位差的当前阶数(j == lg(digit_now * 10eN) )
{
if (Digits[j] == 1 && j != 0)//情况一:大于9且存在非个位的位为1的位数,执行该位降阶求差运算
{
Digits[j] = 9;//降一阶,化1为9
SameOrder_change = 1 * (Digits[j] / 5);
different_SameOrder = different_SameOrder + SameOrder_change * Convert.ToInt32(Math.Pow(10, j - 1));//降1阶差
if (j - 2 >= 0)
{
a = Convert.ToInt32(SameOrder_change != 1);
for (int i = j - 2; i >= 0; i--)
{
different_ReducedOrder = different_ReducedOrder + (Digits[j] + a) * Convert.ToInt32(Math.Pow(9, j - 2 - i)) * Convert.ToInt32(Math.Pow(10, i));//继续降阶
}
}
else
{
different_ReducedOrder = 0 + different_ReducedOrder;//lg(digit_now * 10eN) <= 1时无降二阶以上的位
}
}
else//情况二:大于9且该位非个位不为1,执行该位降阶求差运算
{
SameOrder_change = 1 * (Digits[j] / 5);//同阶位差存在性标志系数(digit_now >= 5)
different_SameOrder = different_SameOrder + SameOrder_change * Convert.ToInt32(Math.Pow(10, j));//同阶差
for (int i = j - 1; i >= 0; i--)
{
different_ReducedOrder = different_ReducedOrder + (Digits[j] - SameOrder_change) * Convert.ToInt32(Math.Pow(9, j - 1 - i)) * Convert.ToInt32(Math.Pow(10, i));//继续降阶
}
}
}
different_result = different_SameOrder + different_ReducedOrder + different_result;
Digits.Clear();
return different_result;
}
static void Main(string[] args)
{
Console.WriteLine("计数规则:缝4添1规则还原真实值,例如100经过了4->5,14->15,24->25.....因此真实值为81,其他数以此类推");
Console.WriteLine("请输入一个整数:");
var x = Convert.ToInt32(Console.ReadLine());
Program program = new Program();
currentTime1 = System.DateTime.Now;
program.real(x);
//后记录时间
currentTime2 = System.DateTime.Now;
Console.WriteLine("真实值为:{0}",(x - difference).ToString());
Console.WriteLine("算法执行时间:" + (currentTime2 - currentTime1).ToString());
Console.ReadKey();
}
}
}
C++代码实现:
#include <iostream>
#include <vector>
#include <cmath>
#include <string>
#include <chrono>
int x;
int difference;
int top_digit;
int times1;
int times2;
std::vector<int> Digits;
int different_find(int times2, int x);
void real(int x)
{
// 获取最高位的值
if (x / 10 != 0)
{
top_digit = x;
while (top_digit >= 10)
{
top_digit /= 10;
}
}
else
{
top_digit = x;
}
times1 = x / top_digit;
times2 = static_cast<int>(std::log10(std::ceil(times1)));
difference = different_find(times2, x);
}
int different_find(int times2, int x) // 获取进位差值
{
int num = x;
Digits.push_back(num % 10); // 生成十进制数的 lg(digit_now * 10eN) == 0 位数字序列
int different_result = 0;
int different_SameOrder = 0;
int different_ReducedOrder = 0;
int SameOrder_change;
int a;
// 获取 Digits 序列
for (int i = 0; i < times2; i++)
{
num /= 10;
Digits.push_back(num % 10); // 生成十进制数的位序列(从 lg(digit_now * 10eN) == 1 位开始计算)
}
for (int j = 0; j < Digits.size(); j++) // j 为求进位差的当前阶数(j == lg(digit_now * 10eN) )
{
if (Digits[j] == 1 && j != 0) // 情况一: 大于9且存在非个位的位为1的位数,执行该位降阶求差运算
{
Digits[j] = 9; // 降一阶,化1为9
SameOrder_change = 1 * (Digits[j] / 5);
different_SameOrder += SameOrder_change * std::pow(10, j - 1);
if (j - 2 >= 0)
{
a = static_cast<int>(SameOrder_change != 1);
for (int i = j - 2; i >= 0; i--)
{
different_ReducedOrder += (Digits[j] + a) * std::pow(9, j - 2 - i) * std::pow(10, i);
}
}
else
{
different_ReducedOrder = 0 + different_ReducedOrder; // lg(digit_now * 10eN) <= 1 时无降二阶以上的位
}
}
else // 情况二: 大于9且该位非个位不为1,执行该位降阶求差运算
{
SameOrder_change = 1 * (Digits[j] / 5); // 同阶位差存在性标志系数(digit_now >= 5)
different_SameOrder += SameOrder_change * std::pow(10, j);
for (int i = j - 1; i >= 0; i--)
{
different_ReducedOrder += (Digits[j] - SameOrder_change) * std::pow(9, j - 1 - i) * std::pow(10, i);
}
}
}
different_result = different_SameOrder + different_ReducedOrder + different_result;
Digits.clear();
return different_result;
}
int main()
{
std::cout << "计数规则:缝4添1规则还原真实值,例如100经过了4->5,14->15...40->50.....因此真实值为81,其他数以此类推" << std::endl;
std::cout << "请输入一个整数:" << std::endl;
std::cin >> x;
real(x);
// 后记录时间
auto start = std::chrono::high_resolution_clock::now();
// program.real(x);
// 后记录时间
auto end = std::chrono::high_resolution_clock::now();
std::cout << "真实值为:" << (x - difference) << std::endl;
std::cout << "算法执行时间:" << std::chrono::duration_cast<std::chrono::microseconds>(end - start).count() << " microseconds" << std::endl;
std::cin.get();
system("pause");
return 0;
}