总数中的特定数字
The particular digit in the number of total
本文关键字:数字 更新时间:2023-10-16
当您有这样的定义时:
int variable = 253243243;
我能以某种方式引用这个数字中的第三个数字吗?沿着矢量或数组的线的东西?我需要这个来比较数字中的某个数字是否对应于用户给出的不同数字。这可能吗?
variable % 1000 / 100
取第三位
一个通用公式是:
(number % pow(base, the_digit_you_want)) / pow(base, the_digit_you_want - 1)
您还必须注意截断/强制转换为int。
您可以通过%
和/
操作的组合提取数字。
或者,您可以使用stringstream
将数字打印到string
,并从字符串中提取数字作为字符:
std::stringstream ss;
ss << variable;
std::string s = ss.str();
unsigned char first = s[0] - '0'; // this is the first digit (from left)
unsigned char second = s[1] - '0'; // this is the second digit (from left)
或者,如果您有幸使用符合C++11的编译器,则可以使用std::string::to_string函数而不是std::stringstream
。
如果您使用C++11,也可以这样做:
int variable = 253243243;
std::string s = std::to_string(variable);
int x = 3; // the position you want
char digit = s[s.size() - 1 - x]; // x position from the right
char otherDigit = s[x - 1]; // x position from the left (1-based)
模除法模式将更有效(就CPU时间和内存而言)。
这个问题让我为数字创建了一个小的"STLish"容器。。。更多的是为了好玩,而不是为了现实生活。然而,它是:
#ifndef __DIGITS_H__
# define __DIGITS_H__
# include <type_traits>
# include <cmath>
# include <cassert>
# include <iterator>
# include <sstream>
# include <algorithm>
namespace digits
{
// Default base type traits, infer base size from the number of character
template <char... Chars>
struct base_char_traits
{
// Mandatory for the digits container, maybe someone want to make
// another traits with wchar ?
typedef char value_type;
// Size of the base, computed from the number of characters passed
static constexpr size_t size = sizeof...(Chars);
// Array of characters use to print the output
static constexpr value_type characters[sizeof...(Chars)] = { Chars... };
};
// **sigh**
// Instantiation of the array of character; otherwise there will be a link
// error
template <char... Chars>
constexpr typename base_char_traits<Chars...>::value_type base_char_traits<Chars...>::characters[sizeof...(Chars)];
// All your bases are belong to us !
struct base2_traits : public base_char_traits<'0', '1'> { };
struct base8_traits : public base_char_traits<'0', '1', '2', '3', '4', '5', '6', '7'> { };
struct base10_traits : public base_char_traits<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'> { };
struct base12_traits : public base_char_traits<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b'> { };
struct base16_traits : public base_char_traits<'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'> { };
// The digit container with the base traits and the type as template
// parameter.
//
// It is a read only container that allows you to iterate on the digit in
// the base given as template parameter.
template <typename BaseTraits, typename T = unsigned long>
class digits
{
public:
// Assert that T fullfil our criteria
static_assert(std::is_integral<T>(), "T must be integral");
static_assert(std::is_unsigned<T>(), "T must be unsigned");
// Value type is defined by the base traits to allow the use of more
// complicated digit type (here we only handle char)
typedef typename BaseTraits::value_type value_type;
// Reference type is defined to be the same as value type because this is an immutable container
typedef typename BaseTraits::value_type reference;
// The size type of the container, i.e. the type that will be used to
// express a digit position
typedef size_t size_type;
// Iterator class allowing one to walk through the number's digit from
// the lowest to the highest
class iterator
{
public:
// Type used to return iterator substraction result
typedef size_t difference_type;
// type used by algorithms (e.g. find)
typedef typename digits::reference reference;
// type used by algorithms (e.g. find)
typedef typename digits::reference pointer;
// type returned by operator*
typedef typename digits::value_type value_type;
// Iterator category, here we can randomly walk in the digit
typedef std::random_access_iterator_tag iterator_category;
// Mandatory default constructor, initialize to an invalid iterator
iterator()
{
_current_digit = 0;
_digits = nullptr;
}
// Build an iterator other a digits container starting at digit
iterator(const digits* digits, size_type digit)
{
_current_digit = digit;
_digits = digits;
}
iterator(const iterator& it) :
iterator(it._digits, it._current_digit)
{
}
// Move using swap idiom
iterator(iterator&& it) :
iterator()
{
swap(*this, it);
}
~iterator()
{
_digits = nullptr;
}
// assignment iterator using swap idiom
iterator& operator=(iterator it)
{
swap(*this, it);
return *this;
}
// Comparison operators
bool operator==(const iterator& it) const
{
assert(_digits == it._digits);
return (_current_digit == it._current_digit);
}
bool operator!=(const iterator& it) const
{
return !(operator==(it));
}
bool operator<(const iterator& it) const
{
assert(_digits == it._digits);
return (_current_digit < it._current_digit);
}
bool operator>(const iterator& it) const
{
assert(_digits == it._digits);
return (_current_digit > it._current_digit);
}
bool operator<=(const iterator& it) const
{
assert(_digits == it._digits);
return (_current_digit <= it._current_digit);
}
bool operator>=(const iterator& it) const
{
assert(_digits == it._digits);
return (_current_digit >= it._current_digit);
}
// Moving the iterator
iterator& operator++()
{
++_current_digit;
return *this;
}
iterator operator++(int)
{
iterator it(*this);
operator++();
return it;
}
iterator& operator--()
{
--_current_digit;
return *this;
}
iterator operator--(int)
{
iterator it(*this);
operator--();
return it;
}
iterator& operator+=(size_type increment)
{
_current_digit += increment;
return *this;
}
iterator operator+(size_type increment) const
{
iterator it(*this);
return (it += increment);
}
friend iterator operator+(size_type increment, const iterator& it)
{
return (it + increment);
}
iterator& operator-=(size_type decrement)
{
_current_digit -= decrement;
return *this;
}
iterator operator-(size_type decrement) const
{
iterator it(*this);
return (it - decrement);
}
difference_type operator-(const iterator& it) const
{
assert(_digits == it._digits);
return (_current_digit - it._current_digit);
}
value_type operator*() const
{
assert(nullptr != _digits);
return _digits->digit(_current_digit);
}
friend void swap(iterator& first, iterator& second)
{
std::swap(first._digits, second._digits);
std::swap(first._current_digit, second._current_digit);
}
private:
// The current digit we will be printing when calling operator*().
// From 0 to (digits.size() - 1)
size_t _current_digit;
// The digit container we're working on.
const digits* _digits;
};
// Define the reverse iterator, that will allow to iterator from the
// highest digit to the lowest (more printing friendly)
typedef std::reverse_iterator<iterator> reverse_iterator;
// Default constructor use 0 as a number
digits()
{
_number = 0;
}
// Build a container over a number given as parameter
digits(T number)
{
_number = number;
}
digits(const digits& copy) :
digits(copy._number)
{
}
// Move constructor using swap idiom
digits(digits&& move) :
digits()
{
swap(*this, move);
}
~digits()
{
}
// Retrieve the digit character
value_type digit(size_t digit) const
{
assert(digit < size());
constexpr size_t base = BaseTraits::size;
// @warning
// llround is mandatory because of a double to unsigned long problem
T modul = static_cast<T>(llround(std::pow(base, digit + 1)));
T div = static_cast<T>(llround(std::pow(base, digit)));
T digit_index = (_number % modul) / div;
return BaseTraits::characters[digit_index];
}
// Assignment using swap idiom
digits& operator=(digits assign)
{
swap(_number, assign._number);
}
// Comparison operator
bool operator==(const digits& comp) const
{
return (_number == comp._number);
}
bool operator!=(const digits& comp) const
{
return !(operator==(comp));
}
// Iterators creation
iterator begin() const
{
return iterator(this, static_cast<size_type>(0));
}
iterator cbegin() const
{
return begin();
}
iterator end() const
{
return iterator(this, size());
}
iterator cend() const
{
return end();
}
reverse_iterator rbegin() const
{
return reverse_iterator(end());
}
reverse_iterator crbegin() const
{
return reverse_iterator(cend());
}
reverse_iterator rend() const
{
return reverse_iterator(begin());
}
reverse_iterator crend() const
{
return reverse_iterator(cbegin());
}
// swap function
friend void swap(digits& first, digits& second)
{
std::swap(first._number, second._number);
}
// cast to string
operator std::string () const
{
std::ostringstream stream;
// print from high to low
std::copy(rbegin(), rend(),
std::ostream_iterator<value_type>(stream, ""));
return stream.str();
}
// The number of digits of this _number
size_type size() const
{
const double log_number = std::log(_number);
constexpr double log_base = std::log(BaseTraits::size);
return std::ceil(log_number / log_base);
}
// The maximum nulber of digits this type can have
size_type max_size() const
{
constexpr double max_number = std::pow(2, sizeof(T) * 8);
constexpr double log_max_number = std::log(max_number);
constexpr double log_base = std::log(BaseTraits::size);
return log_max_number / log_base;
}
private:
// The number we will iterate over the digits
T _number;
};
}
#endif // __DIGITS_H__
基本用法如下:
digits::digits<digits::base10_traits> dig(123456);
for (auto digit: dig)
{
std::cout << "Digit: " << digit << std::endl;
}
我认为,不可变容器(for_each
、find
、copy
等)上的大多数STD算法都可以使用该容器。
这里有一个小测试(头+测试在同一文件中):http://ideone.com/BoMX5Q
好吧,这很没用,但做起来真的很有趣。:)
相关文章:
- 比较并显示使用最小值(a,b)和最大值(a、b)升序排列的4个数字
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- 检查输入是否不是整数或数字
- 如何(从固定列表中)选择一个数字序列,该序列将与目标数字相加
- 如何用数字处理log(0)
- 最高有效数字侧的第N位
- 如何获取一个数字的前3位
- 查找最接近的大于当前数字的数字的索引
- 找到两对数字,使它们的乘积的绝对差最小化
- 我想做一个彼此不同但重复出现的数字
- 将数字转换为字母(例如:123 转换为一二三)
- C++如何计算用户输入的数字中的偶数位数
- 如何在C++中确定文本文件中的元素是字符还是数字
- 打印数字图案
- C++问题:用户认为数字1-100,程序提出问题不超过6次即可得到答案。无法正确
- 如何检查一个c++字符串中有多少相同的字符/数字
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 将数字打印成文字
- 当使用比格式支持的精度更高的精度来显示数字时,会写出什么数据
- 在将数字随机生成为数组期间从内存输出随机数的数组