将我的程序转换成数学公式

Convert my program into a math formula

当我在 reddit 上看到这个数字序列时,一切就开始了 post:

0 1 3 4 6 8 9 10 12 14 16 18 19 20 21 22 24 26 28 30 32 34 36 38 39 40 41 42 43 44 45 46 48 50 52 54 56 58 60 62 64 66 68 70 72 74 76 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 96 98 100 102 104 106 108 110 112 114 116 118 120 122 124 126 128 130 132 134 136 138 140 142 144 146 148 150 152 154 156 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 192 194 196 198 200 202 204 206 208 210 212 214 216 218 220 222 224 226 228 230 232 234 236 238 240 242 244 246 248 250 252 254 256 258 260 262 264 266 268 270 272 274 276 278 280 282 284 286 288 290 292 294 296 298 300 302 304 306 308 310 312 314 316 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 384 386 388 390 392 394 396 398 400 402 404 406 408 410 412 414 416 418 420 422 424 426 428 430 432 434 436 438 440 442 444 446 448 450 452 454 456 458 460 462 464 466 468 470 472 474 476 478 480 482 484 486 488 490 492 494 496 498 500 502 504 506 508 510 512 514 516 518 520 522 524 526 528 530 532 534 536 538 540 542 544 546 548 550 552 554 556 558 560 562 564 566 568 570 572 574 576 578 580 582 584 586 588 590 592 594 596 598 600 602 604 606 608 610 612 614 616 618 620 622 624 626 628 630 632 634 636 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753

正如作者指出的那样:

If you ignore the 0, I figured that it starts adding 2 one time, then 1 one time then 2 two times, 1 two times... 2 2n times, 1 2n times.

这就是为什么我认为很容易想到一个将 return 数字序列的元素 n 的程序。所以我想出了以下代码(在 javascript 中):

function pot(x, y){
    if(y == 0){
        return 1;
    }else{
        return pot(x, --y) * x;
    }
}

function f2(x){
    var n = 0;
    var count = 0;
    var progCount = 0;
    var sw = true;
    var current = 1;
    
    while(progCount < x){
        if(sw){
            current += 2;
        }else{
            current += 1;
        }
        
        count++;
        
        if(pot(2,n) == count){
            if(!sw){
                n++;
            }
            sw = !sw;
            count = 0;
        }
        
        progCount++;
    }
    
    return current;
}

然而我仍然无法将其转换为数学公式...这让我想了很多。我脑子里的某些东西告诉我必须有一种方法可以将这些基本程序转换为数学公式。

这就是我来这里问以下两个问题的原因:

提前致谢。

你可以试试多项式插值

In numerical analysis, polynomial interpolation is the interpolation of a given data set by a polynomial: given some points, find a polynomial which goes exactly through these points.

https://en.wikipedia.org/wiki/Polynomial_interpolation


试试 wolframalpha

http://www.wolframalpha.com/input/?i=interpolate+(1,1)+(2,3)+(3,4)+(4,6)+(5,8)+(6,9)+(7,10)+(8,12)+(9,14)+(10,16)

它给你这个函数(只需复制并粘贴到 javascript,它给你 x[1,10] 之间的解)

f(x) = -x^9/60480+(37 x^8)/40320-(107 x^7)/5040+(767 x^6)/2880-(5677 x^5)/2880+(50539 x^4)/5760-(693913 x^3)/30240+(110741 x^2)/3360-(5897 x)/280+5

x 是您列表的位置
f(x) 是您的解决方案

f(1) = 1
f(2) = 3
f(3) = 4
..
f(10) = 16

f(x>10) = 可能是废话,因为没有已知的数据点

问候

不确定是否对您有帮助,但是:

function fun(n) {
    var result, geo;
    geo = result = parseInt(Math.log(n + 1) / Math.log(2), 10);
    result = ((Math.pow(2, geo) - 2) / 2) * 3;


    var diff = n - (Math.pow(2, geo) - 1);
    geo = Math.pow(2, geo - 1);

    result += (diff >= geo) ? geo * 2 + (diff - geo) : diff * 2;
    return result + 1;
 }

var result = "";
for(var i = 1; i < 100; ++i) {
     result += fun(i) + ", ";
}
console.log(result);

测试到 n = 100。

您可以使用此函数计算任何值。

function f(n) {
    function pow2(n) { return Math.pow(2, n); }

    var t = Math.floor(Math.log(n) / Math.log(2)),
        delta = n - pow2(t);

    return n < 2 ? n : pow2(t) + n - (delta < pow2(t - 1) ? pow2(t - 1) - delta : 1);
}

function f(n) {
    function pow2(n) { return Math.pow(2, n); }

    var t = Math.floor(Math.log(n) / Math.log(2)),
        delta = n - pow2(t);

    return n < 2 ? n : pow2(t) + n - (delta < pow2(t - 1) ? pow2(t - 1) - delta : 1);
}

var i;

for (i = 0; i < 200; i++) {
    document.getElementById('tt').appendChild(document.createTextNode(i + ': ' + f(i) + '\n'));
}
<pre id="tt"></pre>

您可以使用 String.prototype.match()RegExp /\d+/g 将所有数字作为数组获取,Array.prototype.reduceRight()Array.prototype.unshift()Array.prototype.reduce();数学上用加法、减法确定数的差序,从原集合派生的数列重建原集合。

let pattern = `0 1 3 4 6 8 9 10 12 14 16 18 19 20 21 22 24 26 28 30 32 
               34 36 38 39 40 41 42 43 44 45 46 48 50 52 54 56 58 60 62 
               64 66 68 70 72 74 76 78 79 80 81 82 83 84 85 86 87 88 89 
               90 91 92 93 94 96 98 100 102 104 106 108 110 112 114 116 
               118 120 122 124 126 128 130 132 134 136 138 140 142 144 
               146 148 150 152 154 156 158 159 160 161 162 163 164 165 
               166 167 168 169 170 171 172 173 174 175 176 177 178 179 
               180 181 182 183 184 185 186 187 188 189 190 192 194 196 
               198 200 202 204 206 208 210 212 214 216 218 220 222 224 
               226 228 230 232 234 236 238 240 242 244 246 248 250 252 
               254 256 258 260 262 264 266 268 270 272 274 276 278 280 
               282 284 286 288 290 292 294 296 298 300 302 304 306 308 
               310 312 314 316 318 319 320 321 322 323 324 325 326 327 
               328 329 330 331 332 333 334 335 336 337 338 339 340 341 
               342 343 344 345 346 347 348 349 350 351 352 353 354 355 
               356 357 358 359 360 361 362 363 364 365 366 367 368 369 
               370 371 372 373 374 375 376 377 378 379 380 381 382 384 
               386 388 390 392 394 396 398 400 402 404 406 408 410 412 
               414 416 418 420 422 424 426 428 430 432 434 436 438 440 
               442 444 446 448 450 452 454 456 458 460 462 464 466 468 
               470 472 474 476 478 480 482 484 486 488 490 492 494 496 
               498 500 502 504 506 508 510 512 514 516 518 520 522 524 
               526 528 530 532 534 536 538 540 542 544 546 548 550 552 
               554 556 558 560 562 564 566 568 570 572 574 576 578 580 
               582 584 586 588 590 592 594 596 598 600 602 604 606 608 
               610 612 614 616 618 620 622 624 626 628 630 632 634 636 
               638 639 640 641 642 643 644 645 646 647 648 649 650 651 
               652 653 654 655 656 657 658 659 660 661 662 663 664 665 
               666 667 668 669 670 671 672 673 674 675 676 677 678 679 
               680 681 682 683 684 685 686 687 688 689 690 691 692 693 
               694 695 696 697 698 699 700 701 702 703 704 705 706 707 
               708 709 710 711 712 713 714 715 716 717 718 719 720 721 
               722 723 724 725 726 727 728 729 730 731 732 733 734 735 
               736 737 738 739 740 741 742 743 744 745 746 747 748 749 
               750 751 752 753`;

let arr = pattern.match(/\d+/g);

let sequence = [];

let first = arr.reduceRight((a, b) => {sequence.unshift(a-b); return b});

sequence.unshift(+first);

console.log(sequence);

let rebuild = [sequence[0]];

sequence.reduce((a, b) => {rebuild.push(a+b); return rebuild[rebuild.length-1]});

console.log(rebuild);

plnkr http://plnkr.co/edit/DrVDjDTOTNzCJ0sSEk3q?p=preview

当我分析结果时,以下内容适用:

  • 当n是2的幂时,结果总是等于n*1.5
  • 当n是2的幂时,下一个n的结果加上2与result-n-1之差的最大值,例如。 n=8 的结果等于 12,8 是 2 的幂,在这种情况下,以下 n => 结果为 8=>12、9 => 14、10 => 16、12 => 18。其他值直到下一个 n是等次幂加上1

因为这个公式将如下所示:

Math.pow(2, Math.floor(Math.log2(n)))*1.5+n%Math.pow(2,Math.floor(Math.log2(n))) + (n<Math.pow(2, Math.floor(Math.log2(n)))*1.5-1 ? x-Math.pow(2, Math.floor(Math.log2(n))) : Math.pow(2, Math.floor(Math.log2(n)))*0.5-1)

或作为功能:

var fn = function (n) {
    var r0 = Math.pow(2, Math.floor(Math.log2(n)));
    var r1 = r0 * 1.5 + n % r0;
    var r2 = n < r0 * 1.5 - 1 ? n - r0 : r0 * .5 - 1;
    return r1 + r2;
}

以下循环将显示与数字序列相同的结果

for (i = 1; i < 499; i++) {
    console.log(fn(i));
}