自学cocos2d js游戏开发应该按啥步骤进行

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自学cocos2d js游戏开发应该按啥步骤进行相关的知识,希望对你有一定的参考价值。

  跟你简要说一下我的自学路,以免你走弯路

  背景:
  有工作,而且很忙;在不影响工作基础上用业余时间鼓捣(经常会因为工作耽搁学习进度);基本没技术背景(初中qbasic、高中pascal半吊子),大学文科,工作也不是搞代码。因此我感觉我的自学路跟你还是挺契合的。

  1
  两年前的一天,决定要做独立游戏制作人。选定引擎cocos2d,开始学习objective-c语言;(如果你打算只在ios平台开发可以学obj-c配合cocos2d或者sprite kit;如果打算跨平台就要用cocos2d-x和c++了;当然unity什么的也不错但是我还没尝试过,一直很向往)

  2
  我跳过了iOS程序开发(似懂非懂看完了斯坦福那一系列的教学视频),结合当时情况直接选择了cocos2d引擎,这时开始接触 @吴一刀 推荐的博客;我主要看的是子龙山人<子龙山人 - 博客园>、Ray Wenderlich<Ray Wenderlich>、Himi<黑米GameDev街区>这些博客里最基本的例子,知易那个以我当时的水平还看不懂。

  3
  尝试开始设计自己的简单游戏,我做打地鼠!当然比教学例子里的打地鼠复杂多了

  4
  这个过程中发现自己懂的实在是不够,所以又开啃这本书:Learn cocos2d 2 by Steffen Itterheim & Andreas Low

  5
  慢慢的发现需要一些趁手的工具和编辑器,并发展出一套自己构建于cocos2d之上的游戏设计架构。我目前的情况是这样:

  关卡编辑我使用plist文件配合自己写的类;

  sprite sheet使用TexturePacker<TexturePacker>;

  动画/UI编辑最初自己手写太累,后来选择了cocosbuilder,请注意现在这个软件已经停止维护,转而引导用户使用SpriteBuilder<SpriteBuilder>(域名都做了自动跳转;SpriteBuilder我木有研究过,建议你研究一下)。

  粒子编辑我自己还没实际用到,如果真正需要我感觉cocosbuilder的够我用的。//更新:后来用到了ParticleDesigner和cocosbuilder两个软件的粒子编辑混搭

  我当时遇到的一个大麻烦是如何让cocosbuilder、cocos2d版本互相兼容且cocosbuilder无问题。大概情况是这样:cocosbuilder2.1和cocos2d-iphone2.0及2.1版本都不协调怎么办?;What version of Cocosbuilder and Cocos2d-iphone should I choose?

  目前我使用的cocosbuilder 2.1版本(渐变层有bug、并且很可惜动画播放完没有触发消息的机制,我只好把每个动画时长都手动记录一下自己处理)

  ======3月12日更新======
  在 @GarfieldKwong 指点下发现这个版本动画播放完是可以触发消息机制的,更高级版本3.x支持的效果应该是在动画中就加入callback的关键帧
  新技能get√

  具体代码可见下面学习案例的第一个例子里Explosion部分
  =====================

  cocosbuider的学习可以看两个例子Creating a Game with CocosBuilder;Introduction to CocosBuilder;然后就是多用多尝试。

  6
  整个学习过程要学会查资料、学会寻求帮助,我主要用的stackoverflow(话说刚刚发现stackoverflow的reputation喜过15,终于可以投票了:)

  在学习过程中得到了子龙山人(我认为本尊是这位 @屈光辉 )、LearnCocos2d作者Steffen、 @kubisoft 以及众多网上朋友的帮助,再次表示感谢。

  7
  硬件及开发者资格:看完c++开始看obj-c,这个过程一直是使用的vmware虚拟机安装的mac系统写程序;然后入手一个最便宜的mac pro、以及iPhone,尝试玩各种游戏;从看c++开始大约过了1年半(已经有非常简陋的游戏demo)才真正购入iOS开发者资格并开始真机测试。

  8
  尝试过的一些其他工具、各种弯路和坑、以及发散内容:
  可以拖拽方式写代码的stencyl <Stencyl: Make iPhone, iPad, android & Flash Games without code>;
  最初学的不是ojc-c而是谭浩强老师的c++程序设计(虽然有人不喜谭老师,但那书是中文的让我对面对对象程序设计有一些初步的概念,再看英文的obj-c不至于太摸不着头脑,反正手头正好有这么一本买了6年没看的c++。。。);
  尝试过<Tiled Map Editor>但自己目前的坑没有用到;
  尝试过一点物理引擎和粒子,但自己目前的坑没有用到;现在粒子用到了,做了火焰等效果,也挺美的;但是一定要注意CPU占用优化,内存方面我最低支持4S没遇到大问题

  学习音乐制作,这个我小时候学琴一直也喜欢音乐所以有一点点底子,如果没有基础可能上手有门槛;开始用的软件LMMS,但是音源插件在64位系统的问题我一直没解决掉时间精力也不多,所以是暂时停滞了;最近发现Garage Band可能也可以写歌;另外还试过一个很有历史的微软的音乐自动编辑器,很好玩,用来做背景音乐也不错。

  入手手绘板学画画(这中间纠结了好久才决定用位图不用矢量图),如果你能找到热爱游戏的美术同学一起搞那最好不过。但是我一直对画画心痒难搔。。。所以入了这个深坑,晒一晒:
  转载
  z
参考技术A 你可以先去【绘学霸】网站找“游戏设计/游戏制作”板块的【免费】视频教程-【点击进入】完整入门到精通视频教程列表: www.huixueba.net/web/AppWebClient/AllCourseAndResourcePage?type=1&tagid=307&zdhhr-11y04r-1431766191418132019

想要系统的学习可以考虑报一个网络直播课,推荐CGWANG的网络课。老师讲得细,上完还可以回看,还有同类型录播课可以免费学(赠送终身VIP)。

自制能力相对较弱的话,建议还是去好点的培训机构,实力和规模在国内排名前几的大机构,推荐行业龙头:王氏教育。
王氏教育全国直营校区面授课程试听【复制后面链接在浏览器也可打开】: www.huixueba.com.cn/school/3dmodel?type=2&zdhhr-11y04r-1431766191418132019

在“游戏设计/游戏制作”领域的培训机构里,【王氏教育】是国内的老大,且没有加盟分校,都是总部直营的连锁校区。跟很多其它同类型大机构不一样的是:王氏教育每个校区都是实体面授,老师是手把手教,而且有专门的班主任从早盯到晚,爆肝式的学习模式,提升会很快,特别适合基础差的学生。

大家可以先把【绘学霸】APP下载到自己手机,方便碎片时间学习——绘学霸APP下载: www.huixueba.com.cn/Scripts/download.html
参考技术B 程序其实是因为要解决问题才出现的。游戏中的图片资源你甚至都可以找一个安卓的游戏包解压开用他的图片资源,并安装。 同样的。 接着,sdk,然后android ndk。基本包括所有的游戏中的东西,运行一下cocos2d自带的test项目,就是搭建开发环境,如果是windows系统,里边有各种控件的用法,你要安装VS。 接着,有可能你不用安装python。 然后就照着test的控件用法来一步一步的实现你的小游戏,然后就是android的ndk。所以要先构建一个问题,使用cocos创建你的第一个项目,ant等,你可以模仿现有的游戏,不用担心)。使用 cocos 创建你的第一个项目。 如果是mac os系统,你要从苹果商店xcode(这个是的,ant,其实如果不作android游戏的话这些android相关的东西都不用安装,sdk,一点一点的积累相关知识和经验从先构思一个小游戏。这个小游戏。有问题网上搜,添加上环境变量,然后来用cocos2d解决 参考技术C 建议的步骤如下:
1:学习计算机软件开发相关的基础课程,C/C++语言,软件工程,数据结构,操作系统等
2:看cocos2d的源代码,了解它的框架以及核心模块(比如:内存管理,渲染流程,事件,UI)
3:看cocos2d自带的sample
4:下载一个小游戏,研究源码
5:写一个简单的游戏,用c/c++或者lua, js
参考技术D 不得不说,cocos2dx的官方文档实在不是很完善。
但代码里附带的sample还是很不错的。如果你用的是2dx且c++,去看看里面的TestCpp代码,看看官方是如何使用他们自己的方法。这比大多数网上找到的二手教程要好多了。
然后试着按自己的理解去改动或仿写示例代码,看看执行效果是怎样的。
对基本函数了解之后,挑一个小游戏,比如打飞机、俄罗斯方块、马里奥…自己用代码实现一下。如果搞不定,去网上找找别人写的代码研究下,看问题出在哪。
等你做出一个完整的小游戏后,差不多就算开始上路了。
之后,就是一个游戏接一个游戏地写。写不了几十个,你就可以靠这行吃饭了。

应该按啥顺序添加浮点数以获得最精确的结果?

【中文标题】应该按啥顺序添加浮点数以获得最精确的结果?【英文标题】:In which order should floats be added to get the most precise result?应该按什么顺序添加浮点数以获得最精确的结果? 【发布时间】:2011-10-05 15:47:24 【问题描述】:

这是我在最近的采访中被问到的一个问题,我想知道(我实际上不记得数值分析的理论,所以请帮助我:)

如果我们有一些函数,它会累积浮点数:

std::accumulate(v.begin(), v.end(), 0.0);

例如,vstd::vector&lt;float&gt;

在累积这些数字之前对它们进行排序会更好吗?

哪个顺序会给出最准确的答案?

我怀疑将数字按升序排序实际上会使数字错误,但不幸的是我自己无法证明。

附注我确实意识到这可能与现实世界的编程无关,只是好奇。

【问题讨论】:

这实际上与现实世界的编程有关。然而,许多应用程序并不真正关心计算的绝对最佳精度,只要它“非常接近”。工程应用?极其重要。医疗应用?极其重要。大规模统计?稍微低一点的准确性是可以接受的。 请不要回答,除非您确实知道并且可以指向详细解释您的推理的页面。已经有太多关于浮点数的废话了,我们不想再添加了。如果你认为你知道。停止。因为如果你只认为你知道,那么你可能错了。 @Zéychin “工程应用?非常重要。医疗应用?非常重要。”???如果你知道真相,我想你会感到惊讶:) @Zeychin 绝对错误无关紧要。重要的是相对误差。如果百分之几的弧度是 0.001%,那么谁在乎呢? 我非常推荐阅读这篇文章:“每个计算机科学家需要了解的浮点知识”perso.ens-lyon.fr/jean-michel.muller/goldberg.pdf 【参考方案1】:

您的直觉基本上是正确的,按升序(数量级)排序通常会有所改善。考虑我们添加单精度(32 位)浮点数的情况,有 10 亿个值等于 1 /(10 亿),一个值等于 1。如果 1 先出现,那么总和会出现为 1,因为 1 + (1 / 10 亿) 由于精度损失而为 1。每次添加对总数都没有影响。

如果小值首先出现,它们至少会相加,尽管即使那样我也有 2^30 个,而在 2^25 左右之后,我又回到了每个单独不是的情况再影响总量。所以我仍然需要更多技巧。

这是一种极端情况,但通常添加两个幅度相似的值比添加两个幅度非常不同的值更准确,因为您以这种方式“丢弃”较小值的更少精度位。通过对数字进行排序,您可以将大小相似的值组合在一起,并通过将它们按升序添加,您可以为较小的值提供累积达到较大数字大小的“机会”。

不过,如果涉及负数,则很容易“智取”这种方法。考虑三个值的总和,1, -1, 1 billionth。算术上正确的总和是1 billionth,但如果我的第一次加法涉及微小的值,那么我的最终总和将为 0。在 6 个可能的订单中,只有 2 个是“正确的” - 1, -1, 1 billionth-1, 1, 1 billionth。所有 6 个阶数给出的结果在输入中的最大数值范围内是准确的(0.0000001% 出),但其中 4 个的结果在真实解的尺度上是不准确的(100% 出)。您正在解决的特定问题会告诉您前者是否足够好。

事实上,除了按排序顺序添加它们之外,您还可以玩更多的技巧。如果您有很多非常小的值、中等数量的中等值和少量的大值,那么首先将所有小值相加,然后分别合计中等值,再将这两个总计相加可能是最准确的一起然后添加大的。找到最准确的浮点加法组合并非易事,但要应对非常糟糕的情况,您可以将整个数组的运行总计保持在不同的大小,将每个新值添加到与其大小最匹配的总数中,当一个连续的总数开始变得太大时,将其添加到下一个总数中并开始一个新的总数。从逻辑上讲,这个过程相当于以任意精度类型执行求和(所以你会这样做)。但考虑到按数量级升序或降序添加的简单选择,升序是更好的选择。

它确实与现实世界的编程有一定的关系,因为在某些情况下,如果你不小心砍掉了由大量值组成的“重”尾,每个值都太小了,你的计算可能会出现非常严重的错误单独影响总和,或者如果您从许多仅影响总和的最后几位的小值中丢弃过多的精度。在无论如何尾巴可以忽略不计的情况下,您可能不在乎。例如,如果您一开始只将少量值相加,并且只使用总和的几个有效数字。

【讨论】:

+1 用于解释。这有点违反直觉,因为加法通常在数值上是稳定的(与减法和除法不同)。 @Konrad,它可能在数值上是稳定的,但考虑到操作数的大小不同,它并不精确:) @6502:它们按数量级排序,所以 -1 排在最后。如果总和的真实值是 1,那很好。如果您将三个值相加:1 / 十亿、1 和 -1,那么您将得到 0,此时您必须回答一个有趣的实际问题——您是否需要一个准确的答案?真正的总和,还是您只需要一个在最大值范围内准确的答案?对于一些实际应用,后者已经足够好,但如果不是,则需要更复杂的方法。量子物理学使用重整化。 如果你要坚持这个简单的方案,我总是将两个最小的数字相加,然后将总和重新插入集合中。 (好吧,在这里合并排序可能效果最好。您可以使用数组中包含先前求和的数字的部分作为部分和的工作区域。) @Kevin Panko:简单的版本是单精度浮点数有 24 个二进制数字,其中最大的是数字中最大的设置位。因此,如果您将两个幅度相差超过 2^24 的数字加在一起,您将遭受较小值的全部损失,如果它们的幅度相差较小,那么您将损失相应数量的较小的精度号码。【参考方案2】:

还有一种为这种累加运算设计的算法,称为Kahan Summation,您可能应该知道。

根据***,

Kahan 求和算法(也称为补偿求和)显着降低了通过添加有限精度浮点数序列获得的总数中的数值误差,与显而易见的方法。这是通过保持单独的运行补偿(累积小错误的变量)来完成的。

在伪代码中,算法是:

function kahanSum(input)
 var sum = input[1]
 var c = 0.0          //A running compensation for lost low-order bits.
 for i = 2 to input.length
  y = input[i] - c    //So far, so good: c is zero.
  t = sum + y         //Alas, sum is big, y small, so low-order digits of y are lost.
  c = (t - sum) - y   //(t - sum) recovers the high-order part of y; subtracting y recovers -(low part of y)
  sum = t             //Algebraically, c should always be zero. Beware eagerly optimising compilers!
 next i               //Next time around, the lost low part will be added to y in a fresh attempt.
return sum

【讨论】:

+1 可爱的添加到这个线程。任何“热切优化”这些语句的编译器都应该被禁止。 通过使用两个不同大小的求和变量sumc,这是一种几乎将精度提高一倍的简单方法。它可以简单地扩展到 N 个变量。 @ChrisA。好吧,您可以在所有重要的编译器上显式控制它(例如,通过 GCC 上的-ffast-math)。 @Konrad Rudolph 感谢您指出这是-ffast-math 的可能优化。我从这次讨论和this link 中学到的是,如果您关心数值精度,您可能应该避免使用-ffast-math,但在许多应用程序中,您可能受 CPU 限制但不关心精确的数值计算,(例如游戏编程),-ffast-math 使用是合理的。因此,我想修改我措辞强硬的“禁止”评论。 sum, c, t, y 使用双精度变量会有所帮助。您还需要在return sum 之前添加sum -= c【参考方案3】:

我尝试了 Steve Jessop 提供的答案中的极端示例。

#include <iostream>
#include <iomanip>
#include <cmath>

int main()

    long billion = 1000000000;
    double big = 1.0;
    double small = 1e-9;
    double expected = 2.0;

    double sum = big;
    for (long i = 0; i < billion; ++i)
        sum += small;
    std::cout << std::scientific << std::setprecision(1) << big << " + " << billion << " * " << small << " = " <<
        std::fixed << std::setprecision(15) << sum <<
        "    (difference = " << std::fabs(expected - sum) << ")" << std::endl;

    sum = 0;
    for (long i = 0; i < billion; ++i)
        sum += small;
    sum += big;
    std::cout  << std::scientific << std::setprecision(1) << billion << " * " << small << " + " << big << " = " <<
        std::fixed << std::setprecision(15) << sum <<
        "    (difference = " << std::fabs(expected - sum) << ")" << std::endl;

    return 0;

我得到了以下结果:

1.0e+00 + 1000000000 * 1.0e-09 = 2.000000082740371    (difference = 0.000000082740371)
1000000000 * 1.0e-09 + 1.0e+00 = 1.999999992539933    (difference = 0.000000007460067)

第一行的错误是第二行的十倍以上。

如果我在上面的代码中将doubles 更改为floats,我会得到:

1.0e+00 + 1000000000 * 1.0e-09 = 1.000000000000000    (difference = 1.000000000000000)
1000000000 * 1.0e-09 + 1.0e+00 = 1.031250000000000    (difference = 0.968750000000000)

两个答案都没有接近 2.0(但第二个稍微接近)。

如 Daniel Pryden 所述,使用 Kahan 求和(doubles):

#include <iostream>
#include <iomanip>
#include <cmath>

int main()

    long billion = 1000000000;
    double big = 1.0;
    double small = 1e-9;
    double expected = 2.0;

    double sum = big;
    double c = 0.0;
    for (long i = 0; i < billion; ++i) 
        double y = small - c;
        double t = sum + y;
        c = (t - sum) - y;
        sum = t;
    

    std::cout << "Kahan sum  = " << std::fixed << std::setprecision(15) << sum <<
        "    (difference = " << std::fabs(expected - sum) << ")" << std::endl;

    return 0;

我得到的正好是 2.0:

Kahan sum  = 2.000000000000000    (difference = 0.000000000000000)

即使我在上面的代码中将doubles 更改为floats,我也会得到:

Kahan sum  = 2.000000000000000    (difference = 0.000000000000000)

看来Kahan是要走的路!

【讨论】:

我的“大”值等于 1,而不是 1e9。您的第二个答案,按大小顺序添加,在数学上是正确的(10 亿,加上十亿分之一,是 10 亿和 1),尽管更幸运的是该方法的任何一般合理性:-) 请注意 double 没有将十亿分之一加在一起时不会遭受严重的精度损失,因为它有 52 个有效位,而 IEEE float 只有 24 个并且会。 @Steve,我的错误,抱歉。我已将示例代码更新为您想要的。 Kahan 的精度仍然有限​​,但要构造一个杀手级案例,您需要主和和误差累加器c 包含比下一个和数大得多的值。这意味着总和比主要总和要小得多,因此它们中的数量必须非常多才能加起来。尤其是 double 算术。【参考方案4】:

基于史蒂夫的答案,首先按升序对数字进行排序,我将介绍另外两个想法:

    确定两个数字的指数差异,如果超过这个差异,您可能会认为您会损失太多的精度。

    然后按顺序将数字相加,直到累加器的指数对于下一个数字来说太大,然后将累加器放到一个临时队列中,并以下一个数字启动累加器。继续,直到用完原始列表。

您使用临时队列(已对其进行排序)重复该过程,并且指数差异可能更大。

如果你必须一直计算指数,我认为这会很慢。

我快速运行了一个程序,结果是 1.99903

【讨论】:

【参考方案5】:

我认为你可以做得更好,而不是在累积之前对数字进行排序,因为在累积的过程中,累加器会越来越大。如果您有大量相似的数字,您将很快开始失去精度。这是我的建议:

while the list has multiple elements
    remove the two smallest elements from the list
    add them and put the result back in
the single element in the list is the result

当然,这个算法使用优先级队列而不是列表会最有效。 C++代码:

template <typename Queue>
void reduce(Queue& queue)

    typedef typename Queue::value_type vt;
    while (queue.size() > 1)
    
        vt x = queue.top();
        queue.pop();
        vt y = queue.top();
        queue.pop();
        queue.push(x + y);
    

司机:

#include <iterator>
#include <queue>

template <typename Iterator>
typename std::iterator_traits<Iterator>::value_type
reduce(Iterator begin, Iterator end)

    typedef typename std::iterator_traits<Iterator>::value_type vt;
    std::priority_queue<vt> positive_queue;
    positive_queue.push(0);
    std::priority_queue<vt> negative_queue;
    negative_queue.push(0);
    for (; begin != end; ++begin)
    
        vt x = *begin;
        if (x < 0)
        
            negative_queue.push(x);
        
        else
        
            positive_queue.push(-x);
        
    
    reduce(positive_queue);
    reduce(negative_queue);
    return negative_queue.top() - positive_queue.top();

队列中的数字是负数,因为top 产生最大 数字,但我们想要最小。我本可以为队列提供更多模板参数,但这种方法似乎更简单。

【讨论】:

【参考方案6】:

有一类算法可以解决这个确切的问题,无需对数据进行排序或重新排序

换句话说,求和可以在数据上一次完成。这也使得此类算法适用于事先不知道数据集的情况,例如如果数据是实时到达的,需要维护运行总和。

这是最近一篇论文的摘要:

我们提出了一种新颖的在线算法,用于对流进行精确求和 的浮点数。 “在线”是指算法 一次只需要查看一个输入,并且可以取任意一个 此类输入的长度输入流,同时只需要常量 记忆。 “精确”是指我们的内部数组的总和 算法完全等于所有输入的总和,并且 返回的结果是正确舍入的总和。正确性证明 适用于所有输入(包括非规范化数字,但模 中间溢出),并且与被加数的数量无关 或求和的条件数。该算法渐近需要 每个加法运算只有 5 次 FLOP,并且由于指令级并行性 运行速度只比明显的、快速但愚蠢的慢 2--3 倍 当和数为时的“普通递归求和”循环 大于 10,000。因此,据我们所知,它是最快、最 在已知算法中准确且内存效率最高。的确,它 很难看出一个更快的算法或一个需要 如果没有硬件改进,可能存在的 FLOP 会显着减少。 提供大量求和的应用程序。

来源:Algorithm 908: Online Exact Summation of Floating-Point Streams。

【讨论】:

@Inverse:周围仍然有实体库。或者,在线购买 PDF 的费用为 5-15 美元(取决于您是否是 ACM 会员)。最后,DeepDyve 似乎愿意以 2.99 美元的价格将论文借出 24 小时(如果您是 DeepDyve 的新手,您甚至可以在他们的免费试用中免费获得它):deepdyve.com/lp/acm/…【参考方案7】:

这并不能完全回答您的问题,但明智的做法是计算两次总和,一次使用 rounding mode“向上取整”,一次使用“向下取整”。比较这两个答案,您就会知道/如何/您的结果不准确,因此您需要使用更聪明的求和策略。不幸的是,大多数语言并没有让浮点舍入模式变得如此简单,因为人们不知道它在日常计算中实际上是有用的。

看看Interval arithmetic,你在哪里做所有这样的数学运算,随时保持最高和最低值。它带来了一些有趣的结果和优化。

【讨论】:

【参考方案8】:

提高准确性的最简单排序是按绝对值升序排序。这让最小的震级值有机会在与可能导致精度损失的较大震级值交互之前累积或取消。

也就是说,您可以通过跟踪多个不重叠的部分和来做得更好。这是描述该技术并提供准确性证明的论文:www-2.cs.cmu.edu/afs/cs/project/quake/public/papers/robust-arithmetic.ps

该算法和其他精确浮点求和的方法是在简单的 Python 中实现的:http://code.activestate.com/recipes/393090/ 其中至少两个可以简单地转换为 C++。

【讨论】:

【参考方案9】:

您的浮点数应该以双精度添加。这将为您提供比任何其他技术都更高的精度。为了获得更高的精度和更快的速度,您可以创建四个总和,并在最后将它们相加。

如果您要添加双精度数字,请使用 long double 作为总和 - 但是,这只会在 long double 实际上比 double 精度更高的实现中产生积极影响(通常是 x86,PowerPC 取决于编译器设置)。

【讨论】:

“这将为您提供比任何其他技术都更高的精度”您是否意识到您的答案是在较早的一个描述如何使用精确求和的较晚答案之后一年多? “long double”类型太可怕了,你不应该使用它。【参考方案10】:

对于 IEEE 754 单精度或双精度或已知格式的数字,另一种选择是使用由指数索引的数字数组(由调用者传递,或在 C++ 的类中)。将数字添加到数组中时,仅添加具有相同指数的数字(直到找到一个空槽并存储该数字)。当调用求和时,数组从最小到最大求和以最小化截断。单精度示例:

/* clear array */
void clearsum(float asum[256])

size_t i;
    for(i = 0; i < 256; i++)
        asum[i] = 0.f;


/* add a number into array */
void addtosum(float f, float asum[256])

size_t i;
    while(1)
        /* i = exponent of f */
        i = ((size_t)((*(unsigned int *)&f)>>23))&0xff;
        if(i == 0xff)          /* max exponent, could be overflow */
            asum[i] += f;
            return;
        
        if(asum[i] == 0.f)     /* if empty slot store f */
            asum[i] = f;
            return;
        
        f += asum[i];           /* else add slot to f, clear slot */
        asum[i] = 0.f;          /* and continue until empty slot */
    


/* return sum from array */
float returnsum(float asum[256])

float sum = 0.f;
size_t i;
    for(i = 0; i < 256; i++)
        sum += asum[i];
    return sum;

双精度示例:

/* clear array */
void clearsum(double asum[2048])

size_t i;
    for(i = 0; i < 2048; i++)
        asum[i] = 0.;


/* add a number into array */
void addtosum(double d, double asum[2048])

size_t i;
    while(1)
        /* i = exponent of d */
        i = ((size_t)((*(unsigned long long *)&d)>>52))&0x7ff;
        if(i == 0x7ff)         /* max exponent, could be overflow */
            asum[i] += d;
            return;
        
        if(asum[i] == 0.)      /* if empty slot store d */
            asum[i] = d;
            return;
        
        d += asum[i];           /* else add slot to d, clear slot */
        asum[i] = 0.;           /* and continue until empty slot */
    


/* return sum from array */
double returnsum(double asum[2048])

double sum = 0.;
size_t i;
    for(i = 0; i < 2048; i++)
        sum += asum[i];
    return sum;

【讨论】:

这听起来有点像Malcolm 1971 的方法,或者更像是它的变体,它使用Demmel and Hida 的指数(“算法3”)。还有另一种算法可以像您一样执行基于进位的循环,但我目前找不到。 @ZachB - 这个概念类似于bottom up merge sort for linked list,它也使用一个小数组,其中array[i] 指向具有2^i 个节点的列表。我不知道这可以追溯到多远。就我而言,这是 1970 年代的自我发现。【参考方案11】:

关于排序,在我看来,如果您希望取消,那么数字应该以 降序 的数量级添加,而不是升序。例如:

((-1 + 1) + 1e-20) 将给出 1e-20

但是

((1e-20 + 1) - 1) 将给出 0

在第一个等式中,两个大数被抵消,而在第二个等式中,1e-20 项在添加到 1 时会丢失,因为没有足够的精度来保留它。

另外,pairwise summation 非常适合对大量数字求和。

【讨论】:

以上是关于自学cocos2d js游戏开发应该按啥步骤进行的主要内容,如果未能解决你的问题,请参考以下文章

python能做啥游戏

cocos游戏热更方案应该怎么选

如何优化cocos2d程序的内存使用和程序大小

仿《雷霆战机》飞行射击手游开发--游戏简介

如何使用cocos2d

如何优化cocos2d程序的内存使用和程序大小