用分享的方式成长,用有趣的眼光看世界。 

欢迎来到22 26 25的博客 !
热爱编码、算法、知识总结,不定期更新有趣、有料、有营养内容。 让我们共同学习,共同进步。

首发见 知乎 ,如何优雅地利用c++编程从1乘到20?

数学家版本:

#include <iostream>
#include <cmath>
int main()
{std::cout << std::tgamma(20 + 1) << std::endl;
}

语言学家版本:

#include <iostream>
#include <utility>template<std::size_t...I> constexpr auto foo(std::index_sequence<I...>) { return ((I+1) * ...); }int main()
{std::cout << foo(std::make_index_sequence<20>()) << std::endl;
}

“快速”版本:

#include <iostream>
#include <future>long long foo(int a, int b, std::future<long long> last =
std::async(std::integral_constant<long long, 1>())) {return a == b ? a * last.get() : foo((a + b) / 2 + 1, b, std::async(foo, a, (a + b) /
2, std::move(last)));
}int main() {std::cout << foo(1, 20) << std::endl;
}

历史学家版本:

#include <stdio.h>
void main(void) {int i;long long j;for(i = 1, j = 1;i <= 20; j *= i++);printf("%lld", j); }

敏捷开发上线1.0版本:

#include <stdio.h>
int main() {//printf("%d", 1*2*3*4*5*6*7*8*9*10);printf("%lld", (long long)1*2*3*4*5*6*7*8*9*10*11*12*13*14*15*16*17*18*19*20);
}

面向对象专家版本:

#include <iostream>
#include <string>
#include <memory>struct IBaseInterface {virtual ~IBaseInterface() = 0;
};
inline IBaseInterface::~IBaseInterface() = default;struct IDataProvider : virtual public IBaseInterface {virtual int first() = 0;virtual int last() = 0;virtual int next(int v) = 0;
};struct ICalculator : virtual public IBaseInterface {virtual long long calc(IDataProvider *) = 0;
};struct IPrinter : virtual public IBaseInterface {virtual void print(const std::string &) = 0;
};struct ISerializer : virtual public IBaseInterface {virtual std::string serialize(long long value) = 0;
};struct IRunnable : virtual public IBaseInterface {virtual void run() = 0;
};class Foo : virtual public IRunnable {std::shared_ptr<IDataProvider> m_dp;std::shared_ptr<ICalculator> m_c;std::shared_ptr<ISerializer> m_s;std::shared_ptr<IPrinter> m_p;
public:Foo(std::shared_ptr<IDataProvider> dp, std::shared_ptr<ICalculator> c, std::shared_ptr<ISerializer> s, std::shared_ptr<IPrinter> p) : m_dp(std::move(dp)), m_c(std::move(c)), m_s(std::move(s)),m_p(std::move(p)) {}void run() override { return  m_p->print(m_s->serialize(m_c->calc(m_dp.get()))); }
};class DefaultSerializer : virtual public ISerializer {
public:std::string serialize(long long value) override { return std::to_string(value); }
};class StreamPrinter : virtual public IPrinter {std::ostream &m_os;
public:explicit StreamPrinter (std::ostream &os) : m_os(os) {}void print(const std::string &s)  override { m_os << s << std::endl; }
};class MultiplyAccumulateCalculator : virtual public ICalculator {
public:long long calc(IDataProvider *dp) override {int i = dp->first();long long j = i;doj *= (i = dp->next(i));while(i != dp->last());return j;}
};int main() {struct MyDataProvider : virtual public IDataProvider {int first() override { return 1; }int last() override { return 20; }int next(int v) override { return v+1; }};Foo foo(std::make_shared<MyDataProvider>(), std::make_shared<MultiplyAccumulateCalculator>(), std::make_shared<DefaultSerializer>(), std::make_shared<StreamPrinter>(std::cout));foo.run();
}

提前优化的并行版本:

#include <iostream>
#include <xmmintrin.h>double foo(int x) {__m128 a = {1.0f, 2.0f, 3.0f, 4.0f};__m128 b = {4.0f, 4.0f, 4.0f, 4.0f};__m128 c = {1.0f, 1.0f, 1.0f, 1.0f};for(int i = 0; i < x / 4; ++i, a = _mm_add_ps(a, b))c = _mm_mul_ps(c, a);for(int i = x % 4; i < 4; ++i)a[i] = 1.0f;c = _mm_mul_ps(c, a);return (double)c[0] * (double)c[1] * (double)c[2] * (double)c[3];
}int main() {std::cout << foo(20) << std::endl;
}

“宏孩儿”元编程版:

#include <boost/preprocessor.hpp>// 由于boost.preprocessor仅提供255以下的整数运算
// 所以使用sequence来 (十位个位)(千位百位)(十万位万位) 的方式来表示大整数。// 不进位加法:(77)(66)(55) + (44)(33)(22) = (121)(99)(77)
#define PP_ADD_N_N_CARRY_OP(R, DATA, I, ELEM) (BOOST_PP_ADD(BOOST_PP_SEQ_ELEM(I, DATA), ELEM))
#define PP_ADD_N_N_CARRY(SEQ_A, SEQ_B) BOOST_PP_SEQ_FOR_EACH_I(PP_ADD_N_N_CARRY_OP, SEQ_A, SEQ_B)// 进位加法:(121)(99)(77) = (21)(0)(78)
// 注意SEQ_A的长度要比SEQ_B长
#define PP_ADD_N_N_OP(S, STATE, ELEM_CARRY) \BOOST_PP_SEQ_PUSH_FRONT( \BOOST_PP_SEQ_REPLACE(STATE, 0, BOOST_PP_MOD(BOOST_PP_ADD(BOOST_PP_SEQ_HEAD(STATE), ELEM_CARRY), 100)), \BOOST_PP_DIV(BOOST_PP_ADD(BOOST_PP_SEQ_HEAD(STATE), ELEM_CARRY), 100) \)
#define PP_ADD_N_N(SEQ_A, SEQ_B) BOOST_PP_SEQ_REVERSE(BOOST_PP_SEQ_FOLD_LEFT(PP_ADD_N_N_OP, BOOST_PP_SEQ_NIL(0), PP_ADD_N_N_CARRY(SEQ_A, SEQ_B)))// 没什么好说的,X*N = X+X+X+X+X+...+X
#define PP_MUL_N_1_EXP_OP(Z, I, DATA) (DATA)
#define PP_MUL_N_1_EXP(SEQ_N, N) BOOST_PP_REPEAT(N, PP_MUL_N_1_EXP_OP, SEQ_N)
#define PP_MUL_N_1_MYOP(S, STATE, ITEM) PP_ADD_N_N(STATE, ITEM)
#define PP_MUL_N_1_FWD(EXP) BOOST_PP_SEQ_FOLD_LEFT(PP_MUL_N_1_MYOP, BOOST_PP_SEQ_HEAD(EXP), BOOST_PP_SEQ_TAIL(EXP))
#define PP_MUL_N_1(SEQ_N, N) PP_MUL_N_1_FWD(PP_MUL_N_1_EXP(SEQ_N, N))#define FACT5 PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1((1), 2), 3), 4), 5)
#define FACT10 PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(FACT5, 6), 7), 8), 9), 10)
#define FACT15 PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(FACT10, 11), 12), 13), 14), 15)
#define FACT20 PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(FACT15, 16), 17), 18), 19), 20)
#define FACT25 PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(PP_MUL_N_1(FACT20, 21), 22), 23), 24), 25)static_assert(false, BOOST_PP_STRINGIZE(FACT10));

(可能还有更奇怪的算法吧 :)

如果有什么要补充的,欢迎下方

8种方法优雅地利用C++编程从1乘到20相关推荐

  1. Python语言学习:利用python语言实现调用内部命令(python调用Shell脚本)—命令提示符cmd的几种方法

    Python语言学习:利用python语言实现调用内部命令(python调用Shell脚本)-命令提示符cmd的几种方法 目录 利用python语言实现调用内部命令-命令提示符cmd的几种方法 T1. ...

  2. linux中复制字符串出错,C语言实现字符串的复制的两种方法

    本文将要为您介绍的是C语言实现字符串的复制的两种方法,具体操作方法: 利用数组实现 1 #include 2 #include 3 4 void copy_string(char str1[],cha ...

  3. mvc ajax提交html标签,Mvc提交表单的四种方法全程详解

    Mvc提交表单的四种方法全程详解 2019-01-05 编程之家 https://www.jb51.cc 编程之家收集整理的这篇文章主要介绍了Mvc提交表单的四种方法全程详解,编程之家小编觉得挺不错的 ...

  4. 安卓更新UI的几种方法

    安卓更新UI的几种方法: 1.利用Looper更新UI界面   如果我们的代码需要随时将处理后的数据交给UI更新,那么我们想到的方法就是另开一个线程更新数据(也必须这么做,如果我们的数据更新运算量较大 ...

  5. Java求PI的几种方法

    前几天闲的没事,就想用Java算出圆周率,自己想和上网查资料,总结了几种方法. 1.利用概率法,这是算法课上看ppt看到的,大致就是如下,随机掷点,落到扇形里的点数为k,总共为n,当然所有点都落到了正 ...

  6. java 获取区间随机数_Java获取随机数的3种方法

    主要介绍了Java获取随机数的3种方法,主要利用random()函数来实现 方法1 (数据类型)(最小值+Math.random()*(最大值-最小值+1))例: (int)(1+Math.rando ...

  7. 获取表单内部元素的N种方法

    今天讲讲获取表单元素的N种方法~ 以上是部分资料参考的地方:http://blog.csdn.net/h12kjgj/article/details/61624509 先给出一个实例. 输入数字1~1 ...

  8. java equals 判断空_Java 判断字符串是否为空的三种方法与性能分析

    [java中判断字符串是否为数字的三种方法  1>用JAVA自带的函数 public static boolean isNumeric(String str){   for (int i = s ...

  9. java hashmap 去重_java数组去重的两种方法

    我们对于数组元素的使用,有时候在创建数组的初期,并没有考虑过元素的重复问题.当我们想要不重复元素的数组时,就要再进行一步去重的工作.数组的去重有两种方法可以实现,一个是循环比较,另一个是hashSet ...

最新文章

  1. 算法炒房三月亏20多亿!房地产巨头大翻车:房价水太深,AI根本把握不住
  2. Linux(CentOS 7)(64位)系统下安装Pymol(1.8.6)
  3. 大规模 Node.js 网关架构设计与工程实践
  4. 面向对象的思想是什么?
  5. php清空dns缓存文件,怎么清除DNS缓存
  6. void readstring( char s[] ); 怎样_char *s和char s[]
  7. Windos环境用Nginx配置反向代理和负载均衡
  8. 线程安全性的基础知识
  9. 微信 小程序组件 焦点切换
  10. Dubbo本地伪装 Mock
  11. 电脑 u盘 正在计算机,优盘插在电脑上一直显示正在扫描优盘怎么回事
  12. html5都能干嘛种花,把这19种花种起来,整个家都能变成大花园!
  13. [SCOI2009]windy数
  14. cocos2d-x apk 打包路径太深
  15. yocto recipe构建流程介绍
  16. FCN网络(Fully Convolutional Networks)
  17. SVG矢量图怎么做?
  18. 吉大20计算机组成原理大作业,吉大20年9月课程计算机组成原理答案假期吖在线...
  19. 已下载TensorFlow却为什么无法调用?
  20. Python EFZ文件 气象_你要偷偷的学Python,然后惊呆所有人(第四天) - python阿喵

热门文章

  1. 一个携程同时运行三个如何关闭其中一个
  2. 计算机组成原理中机器字长与存储字长的定义,与区别
  3. 零售行业如何开展私域流量运营?试试快鲸scrm
  4. Oracle压测工具 —— SLOB
  5. Isolated User Mode (IUM) Processes(MSDN翻译)
  6. 雷军提议把人工智能当国家战略:要有制度保障
  7. OV2640摄像头移植总结
  8. 什么是vue_cli(转载)
  9. Unity3D-微信跳一跳(一)
  10. Oracle设置表空间自动增长