অনুপাত বজায় রেখে একটি সংখ্যা ব্যাপ্তিকে অন্য ব্যাপ্তিতে রূপান্তর করুন


256

আমি অনুপাত বজায় রেখে একটি সংখ্যার পরিসরকে অন্যটিতে রূপান্তরিত করার চেষ্টা করছি। গণিত আমার দৃ strong় বিন্দু নয়।

আমার একটি চিত্র ফাইল রয়েছে যেখানে পয়েন্টের মানগুলি -16000.00 থেকে 16000.00 পর্যন্ত হতে পারে তবে সাধারণ পরিসীমাটি কম কম হতে পারে। আমি যা করতে চাই তা হ'ল এই মানগুলি পূর্ণসংখ্যার পরিসীমা 0-100 এ সংকুচিত করা হয়, যেখানে 0 হল সর্বনিম্ন পয়েন্টের মান এবং 100 হ'ল বৃহত্তমের মান। এর মধ্যে সমস্ত পয়েন্টগুলির একটি আপেক্ষিক অনুপাত রাখা উচিত যদিও কিছু নির্ভুলতা হারাতে থাকলে আমি পাইথনে এটি করতে চাই তবে এমনকি একটি সাধারণ অ্যালগরিদমও যথেষ্ট। আমি এমন একটি অ্যালগরিদম পছন্দ করব যেখানে সর্বনিম্ন / সর্বোচ্চ বা উভয় ব্যাপ্তি সামঞ্জস্য করা যায় (যেমন, দ্বিতীয় পরিসর 0 থেকে 100 এর পরিবর্তে -50 থেকে 800 হতে পারে)।


আপনাকে উভয়কে ধন্যবাদ, আমি ক্লিটাসকে উত্তর দিচ্ছি কারণ তিনি আমার ফলোআপের উত্তর দেওয়ার জন্য জেরিতে প্রথম স্থান পেয়েছিলেন।
SpliFF

2
সত্যিকারের দুঃখিত ক্লিটাস, আমি এটি জেরিতে দিচ্ছি কারণ সে নতুন এবং তার পয়েন্টগুলির প্রয়োজন।
স্প্লিএফএফ

2
এই যে বয়সবাদ! হেইহে, জে / কে, কোনও উদ্বেগ নেই। :)
ক্লিটাস

7
এই প্রশ্নটি কীভাবে স্ট্যাকওভারফ্লো প্রশ্ন ক্লোজার ব্রিগেড থেকে রক্ষা পেয়েছিল? ;)
থানিক্কল

উত্তর:


533
NewValue = (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin

বা আরও কিছুটা পাঠযোগ্য:

OldRange = (OldMax - OldMin)  
NewRange = (NewMax - NewMin)  
NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin

বা আপনি যদি পুরান পরিসীমা 0 ( ওল্ডমিন = ওল্ডম্যাক্স ) এর ক্ষেত্রে রক্ষা করতে চান :

OldRange = (OldMax - OldMin)
if (OldRange == 0)
    NewValue = NewMin
else
{
    NewRange = (NewMax - NewMin)  
    NewValue = (((OldValue - OldMin) * NewRange) / OldRange) + NewMin
}

মনে রাখবেন যে এক্ষেত্রে আমরা নির্বিচারে সম্ভাব্য নতুন পরিসরের মান বাছাই করতে বাধ্য হয়েছি। প্রসঙ্গের উপর নির্ভর করে, বুদ্ধিমান পছন্দগুলি হতে পারে: NewMin( নমুনা দেখুন ), NewMaxবা(NewMin + NewMax) / 2


ওল্ডম্যাক্সের কি 16000 হতে হবে বা এটি পুরানো পয়েন্ট সেটে সর্বোচ্চ মান হতে পারে (উদাহরণস্বরূপ, 15034.00 বলুন) পার্থক্যটি গুরুত্বপূর্ণ?
স্প্লিএফএফ

5
আপনি এটি যা কিছু করতে চান তা করতে পারেন ... মনে রাখবেন যে কোনও একটি ব্যাপ্তি অপরটির তুলনায় খুব সামান্য হলেও আপনি বিস্মিত ফলাফল পেতে পারেন (ঠিক নিশ্চিত নয়, তবে যদি আকারের মধ্যে 1000000 এর বেশি পার্থক্য থাকে তবে ব্যাপ্তিগুলি, এটি নিশ্চিত করুন যে এটি আপনার প্রত্যাশার মতোই আচরণ করে ... বা ভাসমান পয়েন্টের
অসম্পূর্ণতা

2
এই উত্তরের জনপ্রিয়তা বিবেচনা করে, আরও সাধারণ ক্ষেত্রে আপনার ওল্ডম্যাক্স == ওল্ডমিন সম্ভাবনা বিবেচনা করা উচিত, এটি শূন্য দ্বারা বিভাজন হতে পারে।
ব্যবহারকারী

3
এটা সত্যিই দারুন. এই রূপান্তরটির জন্য কোনও গণিতের নাম আছে?
তারিক

2
একে লিনিয়ার রূপান্তর বলা হয়, @ তারিক
রডরিগো

65

এটি একটি সরল রৈখিক রূপান্তর।

new_value = ( (old_value - old_min) / (old_max - old_min) ) * (new_max - new_min) + new_min

সুতরাং 10000 -16000 থেকে 16000 এর স্কেলে 0 থেকে 100 ফলনের নতুন স্কেলে রূপান্তর করা:

old_value = 10000
old_min = -16000
old_max = 16000
new_min = 0
new_max = 100

new_value = ( ( 10000 - -16000 ) / (16000 - -16000) ) * (100 - 0) + 0
          = 81.25

2
এটা ভুল. বিভাজনের আগে আপনাকে পুরানো মান থেকে ওল্ড মিন বিয়োগ করতে হবে।
এসপিওয়ার্লি

20

আসলে কিছু ক্ষেত্রে রয়েছে যে উপরের উত্তরগুলি ভঙ্গ হবে। যেমন ভুলভাবে ইনপুট মান, ভুলভাবে ইনপুট পরিসর, নেতিবাচক ইনপুট / আউটপুট ব্যাপ্তি।

def remap( x, oMin, oMax, nMin, nMax ):

    #range check
    if oMin == oMax:
        print "Warning: Zero input range"
        return None

    if nMin == nMax:
        print "Warning: Zero output range"
        return None

    #check reversed input range
    reverseInput = False
    oldMin = min( oMin, oMax )
    oldMax = max( oMin, oMax )
    if not oldMin == oMin:
        reverseInput = True

    #check reversed output range
    reverseOutput = False   
    newMin = min( nMin, nMax )
    newMax = max( nMin, nMax )
    if not newMin == nMin :
        reverseOutput = True

    portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
    if reverseInput:
        portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin)

    result = portion + newMin
    if reverseOutput:
        result = newMax - portion

    return result

#test cases
print remap( 25.0, 0.0, 100.0, 1.0, -1.0 ), "==", 0.5
print remap( 25.0, 100.0, -100.0, -1.0, 1.0 ), "==", -0.25
print remap( -125.0, -100.0, -200.0, 1.0, -1.0 ), "==", 0.5
print remap( -125.0, -200.0, -100.0, -1.0, 1.0 ), "==", 0.5
#even when value is out of bound
print remap( -20.0, 0.0, 100.0, 0.0, 1.0 ), "==", -0.2

9

একটি শর্ত আছে, যখন আপনি যা মানগুলি যাচাই করছেন তার সবকটিই একই, যেখানে @ জেরিভিভিএল এর কোডটি এনএএন ফিরে আসবে।

if (OldMin != OldMax && NewMin != NewMax):
    return (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin
else:
    return (NewMax + NewMin) / 2

5

আমি বিএনএফ খনন করিনি জন্য , তবে আরডুইনো ডকুমেন্টেশনে ফাংশনটির দুর্দান্ত উদাহরণ রয়েছে এবং এটি ভেঙে গেছে। আমি পাইথনে এটি পুনরায় পুনর্নির্মাণের জন্য একটি ডিফ নাম পরিবর্তন করে (কারণ মানচিত্রটি একটি অন্তর্নির্মিত) যুক্ত করে এবং টাইপ কাস্টস এবং কোঁকড়ানো ধনুর্বন্ধনীগুলি মুছে ফেলার মাধ্যমে এটি ব্যবহার করতে সক্ষম হয়েছি (অর্থাত্ সমস্ত 'দীর্ঘকালের অপসারণ)।

মূল

long map(long x, long in_min, long in_max, long out_min, long out_max)
{
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

পাইথন

def remap(x, in_min, in_max, out_min, out_max):
  return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min

https://www.arduino.cc/en/reference/map


2

PenguinTD সরবরাহকারী তালিকায়, আমি বুঝতে পারি না কেন রেঞ্জগুলি বিপরীত হয়, এটি রেঞ্জগুলি বিপরীত না করেই কাজ করে। লিনিয়ার পরিসর রূপান্তর রৈখিক সমীকরণ উপর ভিত্তি Y=Xm+nকরে, যেখানে mএবং nপ্রদত্ত রেঞ্জ থেকে উদ্ভূত হয়। রেঞ্জগুলি হিসাবে minএবং উল্লেখ করার চেয়ে maxতাদের 1 এবং 2 হিসাবে উল্লেখ করা ভাল be সুতরাং সূত্রটি হ'ল:

Y = (((X - x1) * (y2 - y1)) / (x2 - x1)) + y1

কোথায় Y=y1কখন X=x1, Y=y2কখন X=x2x1, x2, y1y2কোন দেওয়া যায় positiveবা negativeমান। ম্যাক্রোতে এক্সপ্রেশনটি সংজ্ঞায়িত করা এটিকে আরও দরকারী করে তোলে, এটি পরে কোনও যুক্তিযুক্ত নামের সাথে ব্যবহার করা যেতে পারে।

#define RangeConv(X, x1, x2, y1, y2) (((float)((X - x1) * (y2 - y1)) / (x2 - x1)) + y1)

floatঢালাই ক্ষেত্রে যেখানে সব আর্গুমেন্ট মধ্যে ফ্লোটিং পয়েন্ট বিভাজন নিশ্চিত করবে integerমান। প্রয়োগের উপর নির্ভর করে ব্যাপ্তিগুলি পরীক্ষা করা প্রয়োজন হবে না x1=x2এবং y1==y2


ধন্যবাদ! এখানে সি # রূপান্তর: float RangeConv(float input, float x1, float x2, float y1, float y2) { return (((input - x1) * (y2 - y1)) / (x2 - x1)) + y1; }
জুনায়ার

2

আপনার অনুলিপি এবং পেস্ট স্বাচ্ছন্দ্যের জন্য কয়েকটি সম্পূর্ণ পাইথন ফাংশন এখানে একটি সম্পূর্ণ তালিকা স্কেল করার জন্য একটি ফাংশন রয়েছে।

def scale_number(unscaled, to_min, to_max, from_min, from_max):
    return (to_max-to_min)*(unscaled-from_min)/(from_max-from_min)+to_min

def scale_list(l, to_min, to_max):
    return [scale_number(i, to_min, to_max, min(l), max(l)) for i in l]

যা এর মতো ব্যবহার করা যেতে পারে:

scale_list([1,3,4,5], 0, 100)

[0.0, 50.0, 75.0, 100.0]

আমার ক্ষেত্রে আমি লগারিদমিক বক্ররেখার মতো স্কেল করতে চেয়েছিলাম:

scale_list([math.log(i+1) for i in range(5)], 0, 50)

[0.0, 21.533827903669653, 34.130309724299266, 43.06765580733931, 50.0]


1

আমি জেএস-এ সমাধান করছি এমন একটি সমস্যার মধ্যে আমি এই সমাধানটি ব্যবহার করেছি, তাই আমি ভেবেছিলাম অনুবাদটি শেয়ার করব। ব্যাখ্যা এবং সমাধানের জন্য ধন্যবাদ।

function remap( x, oMin, oMax, nMin, nMax ){
//range check
if (oMin == oMax){
    console.log("Warning: Zero input range");
    return None;
};

if (nMin == nMax){
    console.log("Warning: Zero output range");
    return None
}

//check reversed input range
var reverseInput = false;
oldMin = Math.min( oMin, oMax );
oldMax = Math.max( oMin, oMax );
if (oldMin != oMin){
    reverseInput = true;
}

//check reversed output range
var reverseOutput = false;  
newMin = Math.min( nMin, nMax )
newMax = Math.max( nMin, nMax )
if (newMin != nMin){
    reverseOutput = true;
};

var portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
if (reverseInput){
    portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);
};

var result = portion + newMin
if (reverseOutput){
    result = newMax - portion;
}

return result;
}

ধন্যবাদ! অসাধারণ সমাধান এবং যেতে প্রস্তুত একটি ফাংশন হিসাবে সেট!
আগুনের সাথে ফায়ার ফায়ার

1

সি ++ বৈকল্পিক

আমি পেনগুইনটিডিটির সলিউশন উপযোগী পেয়েছি, সুতরাং কারও যদি এটির প্রয়োজন হয় তবে আমি এটি সি ++ এ পোর্ট করেছিলাম:

ফ্লোট রিম্যাপ (ফ্লোট এক্স, ফ্লোট ওমিন, ফ্লোট ওম্যাক্স, ফ্লোট এনমিন, ফ্লোট এনম্যাক্স) {

//range check
if( oMin == oMax) {
    //std::cout<< "Warning: Zero input range";
    return -1;    }

if( nMin == nMax){
    //std::cout<<"Warning: Zero output range";
    return -1;        }

//check reversed input range
bool reverseInput = false;
float oldMin = min( oMin, oMax );
float oldMax = max( oMin, oMax );
if (oldMin == oMin)
    reverseInput = true;

//check reversed output range
bool reverseOutput = false;  
float newMin = min( nMin, nMax );
float newMax = max( nMin, nMax );
if (newMin == nMin)
    reverseOutput = true;

float portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin);
if (reverseInput)
    portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);

float result = portion + newMin;
if (reverseOutput)
    result = newMax - portion;

return result; }

1

পিএইচপি পোর্ট

PenguinTD এর সমাধানটি সহায়ক হিসাবে খুঁজে পেয়েছি তাই আমি এটি পিএইচপিতে পোর্ট করেছি। নিজেকে সাহায্য করুন!

/**
* =====================================
*              Remap Range            
* =====================================
* - Convert one range to another. (including value)
*
* @param    int $intValue   The value in the old range you wish to convert
* @param    int $oMin       The minimum of the old range
* @param    int $oMax       The maximum of the old range
* @param    int $nMin       The minimum of the new range
* @param    int $nMax       The maximum of the new range
*
* @return   float $fResult  The old value converted to the new range
*/
function remapRange($intValue, $oMin, $oMax, $nMin, $nMax) {
    // Range check
    if ($oMin == $oMax) {
        echo 'Warning: Zero input range';
        return false;
    }

    if ($nMin == $nMax) {
        echo 'Warning: Zero output range';
        return false;
    }

    // Check reversed input range
    $bReverseInput = false;
    $intOldMin = min($oMin, $oMax);
    $intOldMax = max($oMin, $oMax);
    if ($intOldMin != $oMin) {
        $bReverseInput = true;
    }

    // Check reversed output range
    $bReverseOutput = false;
    $intNewMin = min($nMin, $nMax);
    $intNewMax = max($nMin, $nMax);
    if ($intNewMin != $nMin) {
        $bReverseOutput = true;
    }

    $fRatio = ($intValue - $intOldMin) * ($intNewMax - $intNewMin) / ($intOldMax - $intOldMin);
    if ($bReverseInput) {
        $fRatio = ($intOldMax - $intValue) * ($intNewMax - $intNewMin) / ($intOldMax - $intOldMin);
    }

    $fResult = $fRatio + $intNewMin;
    if ($bReverseOutput) {
        $fResult = $intNewMax - $fRatio;
    }

    return $fResult;
}

1

এখানে একটি জাভাস্ক্রিপ্ট সংস্করণ রয়েছে যা একটি ফাংশন দেয় যা পূর্ব নির্ধারিত উত্স এবং গন্তব্য সীমার জন্য পুনরুদ্ধার করে, প্রতিবার করতে হবে এমন গণনার পরিমাণ হ্রাস করে।

// This function returns a function bound to the 
// min/max source & target ranges given.
// oMin, oMax = source
// nMin, nMax = dest.
function makeRangeMapper(oMin, oMax, nMin, nMax ){
    //range check
    if (oMin == oMax){
        console.log("Warning: Zero input range");
        return undefined;
    };

    if (nMin == nMax){
        console.log("Warning: Zero output range");
        return undefined
    }

    //check reversed input range
    var reverseInput = false;
    let oldMin = Math.min( oMin, oMax );
    let oldMax = Math.max( oMin, oMax );
    if (oldMin != oMin){
        reverseInput = true;
    }

    //check reversed output range
    var reverseOutput = false;  
    let newMin = Math.min( nMin, nMax )
    let newMax = Math.max( nMin, nMax )
    if (newMin != nMin){
        reverseOutput = true;
    }

    // Hot-rod the most common case.
    if (!reverseInput && !reverseOutput) {
        let dNew = newMax-newMin;
        let dOld = oldMax-oldMin;
        return (x)=>{
            return ((x-oldMin)* dNew / dOld) + newMin;
        }
    }

    return (x)=>{
        let portion;
        if (reverseInput){
            portion = (oldMax-x)*(newMax-newMin)/(oldMax-oldMin);
        } else {
            portion = (x-oldMin)*(newMax-newMin)/(oldMax-oldMin)
        }
        let result;
        if (reverseOutput){
            result = newMax - portion;
        } else {
            result = portion + newMin;
        }

        return result;
    }   
}

0-180000000, 0x7FFFFFF এ 0-1 স্কেল করতে এই ফাংশনটি ব্যবহার করার উদাহরণ এখানে রয়েছে

let normTo32Fn = makeRangeMapper(0, 1, -0x80000000, 0x7FFFFFFF);
let fs = normTo32Fn(0.5);
let fs2 = normTo32Fn(0);

0

শর্ট কাট / সরলিকৃত প্রস্তাব

 NewRange/OldRange = Handy multiplicand or HM
 Convert OldValue in OldRange to NewValue in NewRange = 
 (OldValue - OldMin x HM) + NewMin

Wayne


1
NewRange/OldRangeএখানে কি ?
জুনেয়ার

0

আমি ব্যক্তিগতভাবে সাহায্যকারী শ্রেণিটি ব্যবহার করি যা জেনেরিকগুলি সমর্থন করে (সুইফট 3 সামঞ্জস্যপূর্ণ)

struct Rescale<Type : BinaryFloatingPoint> {
    typealias RescaleDomain = (lowerBound: Type, upperBound: Type)

    var fromDomain: RescaleDomain
    var toDomain: RescaleDomain

    init(from: RescaleDomain, to: RescaleDomain) {
        self.fromDomain = from
        self.toDomain = to
    }

    func interpolate(_ x: Type ) -> Type {
        return self.toDomain.lowerBound * (1 - x) + self.toDomain.upperBound * x;
    }

    func uninterpolate(_ x: Type) -> Type {
        let b = (self.fromDomain.upperBound - self.fromDomain.lowerBound) != 0 ? self.fromDomain.upperBound - self.fromDomain.lowerBound : 1 / self.fromDomain.upperBound;
        return (x - self.fromDomain.lowerBound) / b
    }

    func rescale(_ x: Type )  -> Type {
        return interpolate( uninterpolate(x) )
    }
}

0

এই উদাহরণটি একটি গানের বর্তমান অবস্থানকে 20 - 40 এর একটি কোণ পরিসরে রূপান্তর করে।

    /// <summary>
    /// This test converts Current songtime to an angle in a range. 
    /// </summary>
    [Fact]
    public void ConvertRangeTests()
    {            
       //Convert a songs time to an angle of a range 20 - 40
        var result = ConvertAndGetCurrentValueOfRange(
            TimeSpan.Zero, TimeSpan.FromMinutes(5.4),
            20, 40, 
            2.7
            );

        Assert.True(result == 30);
    }

    /// <summary>
    /// Gets the current value from the mixValue maxValue range.        
    /// </summary>
    /// <param name="startTime">Start of the song</param>
    /// <param name="duration"></param>
    /// <param name="minValue"></param>
    /// <param name="maxValue"></param>
    /// <param name="value">Current time</param>
    /// <returns></returns>
    public double ConvertAndGetCurrentValueOfRange(
                TimeSpan startTime,
                TimeSpan duration,
                double minValue,
                double maxValue,
                double value)
    {
        var timeRange = duration - startTime;
        var newRange = maxValue - minValue;
        var ratio = newRange / timeRange.TotalMinutes;
        var newValue = value * ratio;
        var currentValue= newValue + minValue;
        return currentValue;
    }

0

বোধন একটি লাইন সমাধান তালিকাভুক্ত করুন

color_array_new = [int((((x - min(node_sizes)) * 99) / (max(node_sizes) - min(node_sizes))) + 1) for x in node_sizes]

দীর্ঘ সংস্করণ

def colour_specter(waste_amount):
color_array = []
OldRange = max(waste_amount) - min(waste_amount)
NewRange = 99
for number_value in waste_amount:
    NewValue = int((((number_value - min(waste_amount)) * NewRange) / OldRange) + 1)
    color_array.append(NewValue)
print(color_array)
return color_array

0

জাভা সংস্করণ

আপনি যা খাওয়ান তা সবসময়ই কাজ করে!

আমি সমস্ত কিছু প্রসারিত রেখেছি যাতে শেখার পক্ষে অনুসরণ করা আরও সহজ। শেষে গোলাকৃতি অবশ্যই alচ্ছিক।

    private long remap(long p, long Amin, long Amax, long Bmin, long Bmax ) {

    double deltaA = Amax - Amin;
    double deltaB = Bmax - Bmin;
    double scale  = deltaB / deltaA;
    double negA   = -1 * Amin;
    double offset = (negA * scale) + Bmin;
    double q      = (p * scale) + offset;
    return Math.round(q);

}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.