一个朋友js图表开发遇到的问题 解决思路c和js
引言
不求知道一切, 只求发现一件
-- 乔治·西蒙·欧姆
附注:那些存在于梦幻中的事迹,那些儿时梦中的人物,每每看起,都觉得 .哎 .... 岁月 ... 一直在努力 ... 哎 ......
愿有 同感受的经历的人 , 今天过的更舒适.
题外话
一个朋友有一次,前不久给我发了一封邮件 介绍 他在写一个js图表插件的自适应代码. 希望我能帮他从 中 找出自适应的数学规律.
他给我的信息 如下:
内容 :
这就是一道数学题,其实我还是觉得挺好玩的,就是老虎吃刺猬,不知道从哪下嘴。
附件 : 自适应max值的情况.txt,内容如下
- var num = 12345 // >100,柱顶数值,我暂且写了12345
- var dotnum = null;//有效数字,恒输入null进行自适应计算
- function FitMKDMax(num,dotnum) {
- //debugger;
- var numMax = Math.round(num*X1); //Math.round 是取整,不保留小数,以下取字符串长度时小数会扰乱计算 X1为第一个想要让你求的值(我目前使用的1.3,这个值肯定在1.25~1.5之间)
- var numlength = numMax.toString().length; //最大值字符串长度
- if(dotnum == null){ //自适应计算有效数字位数
- dotnum = 1 + numlength - Math.round(numMax * X2 / 10).toString().length;//X2是第二个想让你求的值,我目前使用的是3,和X1没有直接关系
- }
- var max = Math.round(num / Math.pow(10, numlength - dotnum)) * Math.pow(10, numlength - dotnum);//Math.round(a,b) 相当于求a的b次方,这里就是一个保留max有效数字位数的计算
- return max;//这里返回的max还不是最终的max,最终的max要看这个max是否整除下面返回的tickInterval,不能整除时(比如max为16k,tickInterval为3k时),会向上取到一个整除值(18k)
- }
- function FitMKDtickInterval(num) {//这里的num和上面方法的num数值相同
- //debugger;
- var tickInterval = Math.round(num * X2 / 10);//同样与以上的X2相同
- tickInterval = Math.round(tickInterval / Math.pow(10, tickInterval.toString().length - 1)) * Math.pow(10, tickInterval.toString().length - 1);//求1位有效数字的四舍五入的计算
- return tickInterval;
- }
- 求X1和X2可以满足num无论是什么数值(100以下过小的数值不算)的情况下,都能保证num这个最高的柱顶保持在y轴max位置向下移动1.5~0.75个单位长度的位置上
- 其中还有一个小要求,就是2.5<X2<3.33,因为是柱形图嘛,如果y轴总共只有2个单位长度不就不好看了么,这样可以保证只要有3个或4个
- 另外这个统计图插件叫highcharts,有时间愿意的话你可以看看,功能还是挺强的。
以上 就是 已知了.
可能看起来 不好懂,至少自己当时看的时候是不明白要干什么的.就知道这是js 代码.
写程序大家都知道,一个别人的模块 改起来比自己写要难. 别人询问你的问题都需要绕一下才能 解决.
这里 我又和 他沟通了一下 经过 自己的理解 得到 信息如下
他需要 输入一个 num 值 例如是 12345 需要 绘制一个图标,这个图标 最高点要比 num大 ,并且为了美观 不能大 1.5个单位,也不能小于 0.75单位.
可能自己说的 很不明白,直接 看代码. 权当没事,看看别人 '劣质'代码,来慰藉一下,
当时 考虑的思路 是 先 通过C写一个 函数 输入 num 输出 他要的数据. 具体的看正文
可能这篇 写的博文很水 但主要 说明两件事
1.数学 才是 最快的解决问题的工具, 还在读书的朋友们注意了
引用一句话, 学好数学,也许买菜都用不到;但 学好数学,她决定你 能在那里买菜.
2 .程序 也许总结 起来不过
输入 => 运算 => 输出
编程还是越简单越好,学了那么多,最后还是觉得面向结构编程 最简单最实用.
正文
在帮他解决问题 中 写了一段C的测试demo,看下面代码 也许上面的业务就明白.有时候,不用 说那么多,直接上代码,什么都明白了.
- #include <stdio.h>
- #include <stdlib.h>
- #include <stdbool.h>
- /*
- * 输入 一个 num 输出 一个 x 和 y x表示 单位值, y表示 最大个数数
- *
- * 需要 4<=y<=6
- * num + 0.75x =< xy <= num + 1.5x
- *
- * 推导 是 y属于 [4,6]
- * num /(y-1.5) >= x >= num/(y-0.75)
- */
- //测试函数
- void test_xy(int num);
- int main(int argc, char *argv[])
- {
- for (int num = ; num < ; ++num)
- test_xy(num);
- system("pause");
- return ;
- }
- static int __gethowidx(float z)
- {
- int d = (int)z;
- while (d > )
- d /= ;
- return d;
- }
- void
- test_xy(int num)
- {
- float xy, xz;
- int yi, zi, y;
- bool flag;
- if (num <= )
- return;
- printf("oldnum = %d ", num);
- for (flag = true; flag; ++num) {
- for (y = ; y <= ; ++y){
- xy = num / (y - 1.5f);
- xz = num / (y - 0.75f);
- yi = __gethowidx(xy);
- zi = __gethowidx(xz);
- if (zi < yi) {
- printf("num = %d => x = %d, y = %d\n", num, yi, y);
- flag = false;
- break;
- }
- }
- }
- }
这是 最初的设计思路, 根据简单线性规划 确定范围,后面计算.
这里 存在两个坑 就是 一个 是 test_xy 中 关于 num++ , 思路是如果找不见 换一个值找找,
但这是不合适的,例如 num = 10000,没找见,最后编程了 num = 15000找见了,这不符合要求.
这个是最初版,但是顺着这个思路 是可行的.下面 写了一个正确 的 js代码.
扯一点,当初学编程的时候,看很多人的代码都看不明白,不知道啥意思, 自己就硬着头皮敲一遍,后来就明白了.
可能编程 是 瓦匠工 + 数学做题 的一种工作,动手和动脑 都需要吧,不管从那个切入点入手,都会学的很好,前提是 你正在 写代码的路上.
后面 我用js重构的时候 , 写了一些 简单注释 , 和自己 解决问题的思路如下
- <!--
- 问题 :
- 输入 一个 num 输出 一个 x 和 y. x表示 单位值, y表示 最大个数.
- (x等价于你给的图中 3k, y等价于你图中的纵轴格子数)
- 已知 :
- 1. 最大格子数在 4-6之间 , 即 4 <= y <= 6 且 y是正整数
- 2. 并且 num距离图顶 最好在 [0.75,1.5] 单位之间 , 即 num + 0.75x <= xy <= num + 1.5x
- 3. 附加一个条件 为了好看 x 最好 是 100,200,...,1000,2000,3000,4000 这种类型的数 即 x % 10^[x]位数 == 0
- 分析 :
- 根据 1,2 有 num / (y - 0.75) <= x <= num / (y - 1.5)
- 其中 y 可取 4,5,6其中一个
- 这样我们可以得到 x 的三个 种类范围
- y = 4 => x ∈ [num/3.75, num/2.5]
- y = 5 => x ∈ [num/4.75, num/3.5]
- y = 6 => x ∈ [num/5.75, num/4.5]
- 上面三种 取数 x y 都可以
- 现在根据 已知 3 , 如果 上面三个 x范围内 有 某个 值 x % 10^[x]位数 == 0 我们就取那个数
- 这里有个容易的算法 是 下面这样 这样 知道 这些 我们 写代码就OK了
- -->
具体的实现如下,一个是 获取x值,一个获取x和y值
- /*
- * 根据范围 [num/3.75, num/2.5] 返回 一个合适 的 x值,如果找不见返回 0
- * 只能 在 getxy函数中使用
- *
- * lnum int : x可取的最小值
- * lnum int : y可取的最大值
- * return : 0表示没有找见符合要求的数,其它就是我们要找的数
- */
- function __getx(lnum, rnum) {
- //得到整数部分就可以了
- lnum = Math.round(lnum);
- rnum = Math.round(rnum);
- //得到二者 字符串
- var lnumstr = String(lnum);
- var rnumstr = String(rnum);
- //得到二者 第一位
- var lc = lnumstr[0] - '0';
- var rc = rnumstr[0] - '0';
- //得到 二者长度
- var ll = lnumstr.length;
- var rl = rnumstr.length;
- // 当 后者 第一位 大于前者 第一位 那么 中间 必定包含 'rc'000 这个数 直接返回
- // 或者 当 后者 比前者 长一位, 那么 也必包含 'rc'000
- if (lc < rc || rl > ll)
- return rc * Math.pow(10, rl - 1);
- //判断一下 特殊情况 假如 lnum 为 整数 那么 直接返回
- if (lc * Math.pow(10, ll - 1) == lnum)
- return lc * Math.pow(10, ll - 1);
- //没有找见
- return 0;
- }
- /*
- * 属于一个 最大的num 返回 x和 y , 没有做安全检查
- *
- * num : 输入值 需要 > 100
- * return : {
- * x => 单位值大小
- * y => 多少个单位值
- * }
- */
- function getxy(num) {
- var x, y;
- for (y = 4; y <= 6; ++y) {
- x = __getx(num / (y - 0.75), num / (y - 1.5));
- if (x != 0) //找见了直接返回结果
- return { "x":x, "y":y};
- } // 我测试了 10000 - 40000 都没有问题
- //如果没找见(找不见情况) 那么 x 设置 为 二者 中间数 例如 4100,4200,4300
- y = 5;
- x = num / (y - 1.5);
- x = Math.round(x);
- fz = Math.pow(10, String(x).length - 2);
- x = x / fz * fz;
- return { "x": x, "y": y };
- }
到这里这个问题是水落石出了. 具体的 js测试demo如下
main.html
- <!DOCTYPE html>
- <html>
- <head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
- <title>这里测试一段js代码</title>
- <meta charset="utf-8" />
- <script type="text/javascript">
- //测试Demo
- function test_demo(num)
- {
- var xy = getxy(num);
- var x = xy.x,y=xy.y;
- var pl = (x*y - num) / x;
- document.writeln("> num = " + num + " => { x = " + x + ", y = " + y + " => " + pl + "}</br>");
- }
- //第一次测试
- //test_demo(12345);
- //test_demo(123456);
- //test_demo(23456);
- //test_demo(2000);
- //第二次测试
- for (var i = 200; i <= 4000000; i+= Math.round(Math.random()*1000))
- test_demo(i);
- </script>
- </head>
- <body>
- </body>
- </html>
上面没写的函数 自己复制加上,再开启一个服务器,基本可以测试了.
最后今天 可能分享的有点水, 可能上面那个问题 说的不好.但是想说的意思是,勤动手,多思考,敢于挑担子帮人解决问题.
写什么样代码都不重要,重要 遇到的问题,需要去解决.方法因需要而生.
下次有机会分享工作中 如何反外挂的手段,或者解读一个云风写的字符串库,我们对它吐槽一下.反正好多.可能 写的都有点水.
让人看得蛋疼.
欢迎吐槽,共同进步.
一个朋友js图表开发遇到的问题 解决思路c和js的更多相关文章
- 一个朋友 js图表开发问题 用 c和 js 解决
引言 不求知道一切, 只求发现一件 -- 乔治·西蒙·欧姆 附注:那些存在于梦幻中的事迹,那些儿时梦中的人物,每每看起,都觉得 .哎 .... 岁月 ... 一直在努力 ... ...
- 最初程序员的思维“修炼”之四——Android平台开发的“强制关闭”解决思路
我和我的朋友参加一个比赛——物联网应用技能大赛,这个大赛所要求的技能有,硬件技术,Android平台开发技术,.NET平台开发技术,所以这是一个团队合作的比赛,基本上没有人能同时掌握这三种技术(在校生 ...
- chart.js图表库案例赏析,饼图添加文字
chart.js图表库案例赏析,饼图添加文字 Chart.js 是一个令人印象深刻的 JavaScript 图表库,建立在 HTML5 Canvas 基础上.目前,它支持6种图表类型(折线图,条形图, ...
- 求剁手的分享,如何简单开发js图表
前段时间做的一个项目里需要用到js图表,在网上找了下,大概找到了highcharts.fusioncharts这些国外产品. 因为都收费,虽然有盗版,我也不敢用,万一被找上们来就砸锅卖铁了要.自己写j ...
- 转-——推荐几个web中常用的一些js图表插件 - zccst
http://www.tuicool.com/articles/bqq2Qn 作者:zccst 我自己用过fusioncharts和highchart. jQuery插件有: TufteGraph f ...
- 推荐几个web中常用js图表插件
作者:zccst 我自己用过fusioncharts和highchart. jQuery插件有: TufteGraph flot js charts jqchart elycharts jquery ...
- 使用JS+Three.js+Echart开发商场室内地图客流信息统计功能
现在的商场管理者在管理商场的同时面临着一些无法避免的问题比如:人员监管不到位.效率低下.商场同质化严重,人流量少等.发现了这些问题作为开发人员的我们怎能视而不见,我们的责任就是发现问题解决问题,提供更 ...
- 第一个mpvue小程序开发总结
前言 说起小程序,其实在去年我都还只试着照着官方文档写过demo的,不过现在这家公司小程序做得比较多,我来之后也参与了几个小程序的开发了,最开始那几个是用的wepy,最近一个开始转用mpvue开发,最 ...
- 学以致用:手把手教你撸一个工具库并打包发布,顺便解决JS浮点数计算精度问题
本文讲解的是怎么实现一个工具库并打包发布到npm给大家使用.本文实现的工具是一个分数计算器,大家考虑如下情况: \[ \sqrt{(((\frac{1}{3}+3.5)*\frac{2}{9}-\fr ...
随机推荐
- 002 The Variables In Csharp
在介绍本章之前,我们先看一下C#的编译过程,如下图所示: 图片摘自:http://www.developingthefuture.net/compilation-process-and-jit-com ...
- Unity Shader : Ghost(残影) v1
前阵子组长给我提了个需求,要实现角色人物的残影.我百度google了一下,发现可以用两种方式实现这个效果:1.记录前几帧的人物位置,将其传入shader中,对每个位置进行一个pass渲染.2. 通过相 ...
- Android开发-API指南-<supports-gl-texture>
<supports-gl-texture> 英文原文:http://developer.android.com/guide/topics/manifest/supports-gl-text ...
- 在Service Fabric上部署Java应用,体验一把微服务的自动切换
虽然Service Fabric的Java支持版本还没有正式发布,但是Service Fabric本身的服务管理.部署.升级等功能是非常好用的,那么Java的开发者可以如何利用上Service Fab ...
- LICEcap GIF 屏幕录制工具
LICEcap 是一款屏幕录制工具,支持导出git动画图片格式,简单好用.大小只有几百KB 运行之后,可以随意调整大小,右下角有开始/停止按钮. 压缩包:http://files.cnb ...
- NTP服务器地址及IP
yum install ntp */20 * * * * /usr/sbin/ntpdate 61.172.254.29 210.72.145.44 (国家授时中心服务器IP地址)133.100.11 ...
- python字符串常用操作方法
python字符串操作常用操作,如字符串的替换.删除.截取.复制.连接.比较.查找.分割等,需要的朋友可以参考下. 1.去除空格str.strip():删除字符串两边的指定字符,括号的写入指定字符,默 ...
- 集群监控系统Ganglia应用案例
集群监控系统Ganglia应用案例 --我们把集群系统投入生产环境后,这时就需要一套可视化的工具来监视集群系统,这将有助于我们迅速地了解机群的整体配置情况,准确地把握机群各个监控节点的信息,全面地察看 ...
- TCP/IP之大明王朝邮差
一位大神的精华之作,原创2016-05-12 刘欣 来自码农翻身! 时间: 大明王朝天启四年, 清晨. 天色刚蒙蒙亮,我就赶着装满货物的马车来到了南城门,这里是集中处理货物的地方,一队一队的马车都来到 ...
- 获取Spring的上下文环境ApplicationContext的方式
摘自: http://blog.csdn.net/yang123111/article/details/32099329 获取Spring的上下文环境ApplicationContext的方式 Web ...