一个朋友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 = 30000; num < 40000; ++num)
        test_xy(num);

    system("pause");
    return 0;
}

static int __gethowidx(float z)
{
    int d = (int)z;

    while (d > 10)
        d /= 10;

    return d;
}

void
test_xy(int num)
{
    float xy, xz;
    int yi, zi, y;
    bool flag;

    if (num <= 100)
        return;

    printf("oldnum = %d ", num);
    for (flag = true; flag; ++num) {
        for (y = 4; y <= 6; ++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>

上面没写的函数 自己复制加上,再开启一个服务器,基本可以测试了.

最后今天 可能分享的有点水, 可能上面那个问题 说的不好.但是想说的意思是,勤动手,多思考,敢于挑担子帮人解决问题.

写什么样代码都不重要,重要 遇到的问题,需要去解决.方法因需要而生.

下次有机会分享工作中 如何反外挂的手段,或者解读一个云风写的字符串库,我们对它吐槽一下.反正好多.可能 写的都有点水.

让人看得蛋疼.

欢迎吐槽,共同进步.

时间: 2024-10-23 18:21:10

一个朋友js图表开发遇到的问题 解决思路c和js的相关文章

最初程序员的思维“修炼”之四——Android平台开发的“强制关闭”解决思路

我和我的朋友参加一个比赛——物联网应用技能大赛,这个大赛所要求的技能有,硬件技术,Android平台开发技术,.NET平台开发技术,所以这是一个团队合作的比赛,基本上没有人能同时掌握这三种技术(在校生). 今天的一个任务是:串口通讯实验.面向Android平台开发,要求把Android工程部署到测试机上,然后打开串口为COM1,COM2,COM3及相应波特率的串口. 我们碰到的问题是,Android工程部署上之后,弹出“强制关闭”的消息框. 以下是我对”强制关闭“的理解: Android程序,弹

chart.js图表库案例赏析,饼图添加文字

chart.js图表库案例赏析,饼图添加文字 Chart.js 是一个令人印象深刻的 JavaScript 图表库,建立在 HTML5 Canvas 基础上.目前,它支持6种图表类型(折线图,条形图,雷达图,饼图,柱状图和极地区域区).而且,这是一个独立的包,不依赖第三方 JavaScript 库,小于 5KB. 前天用了一下,由于以前也稍微用过,今天总结了一下(水平有限,如果问题,请不吝赐教): 开发中文文档:http://www.bootcss.com/p/chart.js/docs/ ch

[3] 用D3.js做一个简单的图表吧!

本人的个人博客为: www.ourd3js.com csdn博客为: blog.csdn.net/lzhlzz 转载请注明出处,谢谢. 前面说了几节,都是对文字进行处理,这一节中将用 D3.js 做一个简单的柱形图. 做柱形图有很多种方法,比如用 HTML 的 div 标签,或用 svg . 推荐用 SVG 来做各种图形.SVG 意为可缩放矢量图形(Scalable Vector Graphics),SVG 使用 XML 格式定义图像,不清楚什么是SVG的朋友请先在 w3cschools 学习下

求剁手的分享,如何简单开发js图表

前段时间做的一个项目里需要用到js图表,在网上找了下,大概找到了highcharts.fusioncharts这些国外产品. 因为都收费,虽然有盗版,我也不敢用,万一被找上们来就砸锅卖铁了要.自己写js图表,要累死肯定也不能这么做,找到了一个国内的免费产品okaycharts. 上图看图表效果: 简单对OKAYCHARTS做下评价: 本地设计器设计图表,预览图表调整效果,然后一键导出js代码,方便多了,这一特性直接改变了我对js图表的使用印象.图表类型还可以,常用的都有了.

用Vue.js来开发一个电影App的前端部分

我们要构建一个什么样的App? 我们大多数人使用在线流媒体服务(如Netflix)观看我们最喜欢的电影或者节目.这篇文章将重点介绍如何通过使用vue.js 2建立一个类似风格的电影流媒体WEB交互界面(见上图). 最终的产品可以去这里找:https://codepen.io/itslit/full/mvvjzr. 尽管Bulma将作为应用的CSS框架,但是本文将主要集中在Vue.js的使用和浏览CSS式样,如果你想跟着学,我设置了一个可以作为开始学习的地方,所有自定义组合,初始数据对象和必要的需

推荐三款强大的Js图表库

1.百度的Echart ECharts,缩写来自Enterprise Charts,是百度推出的一款开源的,商业级数据图表,它最初是为了满足百度公司商业体系里各种业务系统(如凤巢.广告管家等等)的报表需求. 2.Highcharts 中文网站:http://www.hcharts.cn/ Highcharts是国外的一款功能强大.开源.美观.图表丰富.兼容绝大多数浏览器的纯js图表库.Highcharts针对个人用户及非商业用途免费,商业用途需要购买授权. 3.阿里的G2 G2(The Gram

第一个mpvue小程序开发总结

前言 说起小程序,其实在去年我都还只试着照着官方文档写过demo的,不过现在这家公司小程序做得比较多,我来之后也参与了几个小程序的开发了,最开始那几个是用的wepy,最近一个开始转用mpvue开发,最近这个项目终于上线了,我也来试着总结回顾一波吧. 关于框架的选择 我刚来现在的公司时,我就了解过有一个小程序框架叫mpvue被美团开源了,有过一个大致的了解.来了公司之后了解到我们公司已经有了一套自己的小程序技术栈那就是基于wepy的,而不是原生小程序,毕竟我们要开发的小程序不是简单的几个页面,而且

一个网站或者APP开发要多少钱

经常遇到朋友问我:"开发一个京东商城需要多少钱?开发一个滴滴打车需要多少钱?"类似这样的需求,就连我这样一名伪开发者都不愿意去骗客户或者朋友,因为这种问题是很难回答出来的.为什么这么说呢?要知道类似京东商城滴滴打车这样亿级别用户的产品,很难知道他之前经过了多少次版本的迭代,也很难知道他的产品线有多广,很多朋友甚至连"迭代"这样的名词具体概念都不懂,今天我会以Q+A的形式汇总诸多开发过程中遇到的客户问题,希望能给创业中的你一些建议,如果你是一名开发者可以绕道. 首先我

chrome扩展程序开发之在目标页面运行自己的JS

大家都知道JS是运行在客户端的,所以,如果我们自己写一个浏览器的话,是一定可以往下载下来的网页源代码中加入js的.可惜我们没有这个能力.不过幸运的是,chrome的扩展程序可以帮我们做到这件事. Google Chrome是一个很强大的浏览器,提供了各种各样的插件,大大提升了使用了的效率,比如vimium.honx等. Google在提供这些插件的同时还允许用户开发自己的插件. 最近在写js的脚本采集程序,需要测试在网页中的运行情况,因此可以利用Chrome插件进行测试. 本文会做一个chrom