簡體   English   中英

夾緊“簡單”數字

[英]Clamping to “easy” numbers

所以我正在嘗試創建一個圖形應用程序,我正在使用Desmos作為基礎。

我正在努力解決的問題是Desmos處理軸的細分方式。 當您放大或縮小時,刻度始終是“簡單”的簡單數字,如5,100,1000等。所以我的問題是:如何通過任何級別的縮放簡化其比例?

BTW:使用C ++

我將編寫一個關於如何執行此操作的說明,但后來我意識到代碼可能比解釋更容易。


最重要的一步:准確定義“簡單”數字的含義。


示例#1:1,2,4,8,16,32,64,128,...,1073741824,...

這些是兩個人的權力。 因此,一個簡單的ceil(log(x)/log(2.0))將解決它。


示例#2:1,2,5,10,20,50,100,200,500,1000,2000,5000,10000,......

兩種力量的混合,以及它的一些倍數。 讓我們仔細看看。

  • 這些中的一部分可以被描述為十的冪。
    • 將公式更改為ceil(log(x)/log(10.0))將解決它。
  • 對於每個十次冪,其乘以2.05.0倍數也是“簡單的簡單數字”。
    • 在每次迭代內部,在檢查十次冪值后,還要檢查兩個倍數。 如果它適合多個中的一個,則可以返回該值作為結果。

以下代碼僅用於解釋該概念。 它效率不高 - 一個高效的版本應該使用對數來得到O(1)時間的結果。


#include <iostream>
#include <vector>
#include <limits>
#include <stdexcept>
#include <algorithm>

using namespace std;

double getNiceAxisLength(double value, double baseLength, double step, const std::vector<double>& subSteps)
{
    typedef std::vector<double>::const_iterator VecDoubleIter;
    if (value < 0.0)
    {
        throw std::invalid_argument("Error: value must be non-negative. Take absolute value if necessary.");
    }
    if (baseLength <= 0.0)
    {
        throw std::invalid_argument("Error: baseLength must be positive.");
    }
    if (step <= 1.0)
    {
        throw std::invalid_argument("Error: step must be strictly greater than 1.");
    }
    for (VecDoubleIter iter = subSteps.begin(); iter != subSteps.end(); ++iter)
    {
        double subStep = *iter;
        if (subStep <= 1.0 || subStep >= step)
        {
            throw std::invalid_argument("Error: each subStep must be strictly greater than 1, and strictly smaller than step.");
        }
    }
    // make ascending.
    std::vector<double> sortedSubSteps(subSteps.begin(), subSteps.end());
    std::sort(sortedSubSteps.begin(), sortedSubSteps.end());
    if (value <= baseLength)
    {
        return baseLength;
    }
    double length = baseLength;
    double terminateLength = numeric_limits<double>::max() / step;
    while (length < terminateLength)
    {
        for (VecDoubleIter iter = sortedSubSteps.begin(); iter != sortedSubSteps.end(); ++iter)
        {
            double subStep = *iter;
            if (value <= length * subStep)
            {
                return (length * subStep);
            }
        }
        double nextLength = length * step;
        if (value <= nextLength)
        {
            return nextLength;
        }
        length = nextLength;
    }
    return baseLength;
}

int main()
{
    double baseLength = 1.0;
    double step = 10.0;
    std::vector<double> subSteps;
    subSteps.push_back(2.5);
    subSteps.push_back(5);
    for (int k = 0; k < 1000; k += ((k >> 2) + 1))
    {
        double value = k;
        double result = getNiceAxisLength(value, baseLength, step, subSteps);
        cout << "k: " << value << " result: " << result << endl;
    }

    cout << "Hello world!" << endl;
    return 0;
}

產量

k: 0 result: 1
k: 1 result: 1
k: 2 result: 2.5
k: 3 result: 5
k: 4 result: 5
k: 6 result: 10
k: 8 result: 10
k: 11 result: 25
k: 14 result: 25
k: 18 result: 25
k: 23 result: 25
k: 29 result: 50
k: 37 result: 50
k: 47 result: 50
k: 59 result: 100
k: 74 result: 100
k: 93 result: 100
k: 117 result: 250
k: 147 result: 250
k: 184 result: 250
k: 231 result: 250
k: 289 result: 500
k: 362 result: 500
k: 453 result: 500
k: 567 result: 1000
k: 709 result: 1000
k: 887 result: 1000
Hello world!

你好,世界!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM