নেট থেকে "ক্ল্যাম্প" ফাংশনটি কোথায় পাব?


98

আমি xএকটি ব্যাপ্তির মান বাছাই করতে চাই [a, b]:

x = (x < a) ? a : ((x > b) ? b : x);

এটি বেশ বেসিক is অন্তত না - কিন্তু আমি বর্গ লাইব্রেরিতে একটি ফাংশন "বাতা" দেখতে না পান System.Math

("ক্ল্যাম্প" অজ্ঞাত হওয়ার জন্য একটি মান হ'ল এটি নিশ্চিত করা হয় যে এটি কোনও সর্বোচ্চ এবং সর্বনিম্ন মানের মধ্যে রয়েছে। এটি যদি সর্বোচ্চ মানের চেয়ে বেশি হয় তবে এটি সর্বাধিক ইত্যাদি দ্বারা প্রতিস্থাপিত হয়))


4
@ ডানভিল: "সি # ক্লাস লাইব্রেরি" নেই। আপনার অর্থ "দ। নেট ফ্রেমওয়ার্ক"।
জন স্যান্ডার্স

4
সি # 7.1 হিসাবে এখনও কিছুই নেই?
জোসে

4
@JohnSaunders আমি যে কঠোরভাবে সত্য বিশ্বাস করে না stackoverflow.com/questions/807880/...
আদম নেইলর

যদি আমি জিজ্ঞাসা করি কীভাবে বিশ্বের প্রতিটি এক ইংরেজী স্পিকার প্রোগ্রামার একটি মানকে "সীমাবদ্ধ" করতে পারে তবে আমি কী বোঝাতে চাইছিলাম তা তাত্ক্ষণিকভাবে জানতে পারব। সম্ভবত প্রতিটি প্রোগ্রামার জানত। ব্যবসায়ের 30+ বছর পরে আজ আমাকে "ক্ল্যাম্প" বলতে কী বোঝায় তা খুঁজে বের করতে হয়েছিল। "নির্ভরতা ইনজেকশন" এর অনুরূপ - "প্যারামিটারাইজেশন" এমন একটি স্পষ্ট বিষয় যা এর উপরে কেউ কখনও কোনও বই লেখেনি।
বব

@ Bob কিছু শব্দের historicalতিহাসিক, সুস্পষ্ট সংজ্ঞা রয়েছে have বাতা তাদের মধ্যে অন্যতম। en.wikedia.org/wiki/Clamping_ ( راف ics ) বা khronos.org/registry/OpenGL-Refpages/gl4/html/clamp.xhtml বা ডকস.মাইক্রোসফট / en- us / windows/ win32 / direct3dhlsl/… "সীমাবদ্ধতা "বিভ্রান্তিকর হবে, বিশেষত" সীমা "এর আগে থেকেই গণিতে আলাদা অর্থ রয়েছে।
ক্যালাস

উত্তর:


141

আপনি একটি এক্সটেনশন পদ্ধতি লিখতে পারেন:

public static T Clamp<T>(this T val, T min, T max) where T : IComparable<T>
{
    if (val.CompareTo(min) < 0) return min;
    else if(val.CompareTo(max) > 0) return max;
    else return val;
}

স্ট্যাটিক ক্লাসে এক্সটেনশন পদ্ধতিগুলি যায় - যেহেতু এটি বেশ নিম্ন-স্তরের ফাংশন, এটি সম্ভবত আপনার প্রকল্পের কোনও মূল নেমস্পেসে যেতে হবে। তারপরে আপনি যেকোন কোড ফাইলে পদ্ধতিটি ব্যবহার করতে পারেন যা নামের স্থানের জন্য যেমন কোনও নির্দেশিকা ব্যবহার করে

using Core.ExtensionMethods

int i = 4.Clamp(1, 3);

.NET কোর 2.0

.NET কোর 2.0 দিয়ে শুরু করে System.Mathএখন একটি Clampপদ্ধতি রয়েছে যা পরিবর্তে ব্যবহার করা যেতে পারে:

using System;

int i = Math.Clamp(4, 1, 3);

4
আমি এটি কোথায় রাখব এবং <(অবিচ্ছেদ্য ধরণের জন্য) সাথে তুলনা করার চেয়ে তুলনা তুলনামূলকভাবে ধীরে ধীরে কল করছি?
ড্যানভিল

4
একটি স্ট্যাটিক ক্লাসে এবং .NET ফ্রেমওয়ার্কে (মনো, কমপ্যাক্ট, ইত্যাদি সম্পর্কে নিশ্চিত নয়), জেনেরিকটি টাইপের জন্য পুনরায় কম্পাইল করা উচিত, এবং তুলনা করার জন্য ইনলাইন করা উচিত, সুতরাং কোনও পারফরম্যান্স পেনাল্টি নেই।
রবার্ট ফ্রেজার

4
@ ফ্রেসিয়ার যদি না এটি অতি সম্পাদন সংবেদনশীল কোড হয় তবে আপনি এটি করার মাধ্যমে কোনও অর্থবহ পারফরম্যান্স লাভ করার সম্ভাবনা কম। এটি জেনেরিক হওয়া সম্ভবত কয়েকটি মাইক্রোসেকেন্ড সংরক্ষণের চেয়ে বেশি কার্যকর।
MgSam

4
জেনেরিক সংস্করণে সীমাবদ্ধ করার পক্ষে ভাল বিষয়টি IComparableহল যে কোনও বক্সিং হয় না। এটি খুব দ্রুত চালানো উচিত। মনে রাখবেন doubleএবং এর সাথে float, CompareToপদ্ধতিটি মোট ক্রমের সাথে সামঞ্জস্য হয় যেখানে NaNসহ অন্যান্য সমস্ত মানের চেয়ে কম NegativeInfinity। সুতরাং এটি <অপারেটরের সমতুল্য নয় । যদি আপনি <একটি ভাসমান-পয়েন্ট টাইপ ব্যবহার করেন তবে আপনাকে কীভাবে চিকিত্সা করবেন তা বিবেচনা NaNকরতে হবে। অন্যান্য সংখ্যার জন্য এটি প্রাসঙ্গিক নয়।
জেপ্প স্টিগ নীলসন

4
NaNউভয় ক্ষেত্রেই কীভাবে চিকিত্সা করা যায় তা বিবেচনা করতে হবে । সঙ্গে সংস্করণ <এবং >আউটপুট would NaNএবং ব্যবহার NaNজন্য minঅথবা maxকার্যকরভাবে একতরফা বাতা করতে হবে। সঙ্গে CompareToএটা সবসময় ফিরে আসবে NaNযদি maxহয় NaN
হারমান

32

শুধু ব্যবহার করুন Math.Minএবং Math.Max:

x = Math.Min(Math.Max(x, a), b);

এটি int a0 = x > a ? x : a; return a0 < b ? a0 : bকোনটি অনুবাদ করে (যদিও সঠিক ফলাফল দেয়) ঠিক আদর্শ নয়।
মিঃ স্মিথ

12
এবং এটা কেন?
d7samurai

4
@ d7samurai আমরা যদি জানি যে মিনিট <= সর্বাধিক, Math.Min(Math.Max(x, min), max)x <min হলে প্রয়োজনের তুলনায় আরও একটি তুলনামূলক ফলাফল।
জিম বাল্টার

@ জিমবাল্টার, তাত্ত্বিকভাবে এটি সত্য। আপনি যদি তুলনামূলকভাবে () সাধারণত কার্যকরভাবে প্রয়োগ করেন তা দেখে, গৃহীত উত্তরটি 6 টি তুলনা পর্যন্ত নিতে পারে। যদিও আমি জানি না, যদি সংকলকটি যথেষ্ট স্মার্ট হয় এবং তুলনামূলক () তুলনায় ইনলাইন করে এবং অপ্রয়োজনীয় তুলনাগুলি সরিয়ে দেয়।
কুইনমার্স

4
এটি কেবল ক্ষেত্রে একবার করার দরকার পরে এটির জন্য ভাল, তারপরে পুরো নতুন ফাংশনটি ওভারকিলের মতো মনে হয়।
feos

26

চেষ্টা করুন:

public static int Clamp(int value, int min, int max)  
{  
    return (value < min) ? min : (value > max) ? max : value;  
}

7
উঘ! সেই কুৎসিত অপ্রয়োজনীয় প্রথম বন্ধনী! আপনি যদি ডাবল টার্নারি অপারেটরগুলির সাথে একটি খারাপ প্রতিভা হতে চলেছেন তবে কমপক্ষে এটি সঠিকভাবে করুন এবং সেগুলি থেকেও মুক্তি পান! ।
XenoRo

9
@ XenoRo এই "অপ্রয়োজনীয়" প্রথম বন্ধনই এটিকে পাঠযোগ্য করে তোলে।
ক্লিয়ারার

4
@ ক্লিনার - ১) আপনি যদি পঠনযোগ্যতার জন্য যাচ্ছেন তবে ডাবল টেন্নারিগুলি এড়ানো হবে এবং যদি এর পরিবর্তে ব্লকগুলি ব্যবহার করা হত। 2) আপনি রসিকতা পান না, তাই না? এক্সডি
জেনোরোর

13

একটি নেই, তবে এটি তৈরি করা খুব বেশি কঠিন নয়। আমি এখানে একটি পেয়েছি: বাতা

এইটা:

public static T Clamp<T>(T value, T max, T min)
    where T : System.IComparable<T> {
        T result = value;
        if (value.CompareTo(max) > 0)
            result = max;
        if (value.CompareTo(min) < 0)
            result = min;
        return result;
    }

এবং এটি ব্যবহার করা যেতে পারে:

int i = Clamp(12, 10, 0); -> i == 10
double d = Clamp(4.5, 10.0, 0.0); -> d == 4.5

এই সমাধানটি গৃহীত একের চেয়ে ভাল। অস্পষ্টতা নেই।
অ্যাগসোল

6
@ কোডক্লাউন এই সমাধানটির ফলে মান> সর্বোচ্চ এবং বিপরীত যুক্তি আদেশটি বাগ (এবং কার্যত গ্যারান্টি) দেয় ites আমি জানি না যে আপনি কী অস্পষ্টতাকে এড়িয়ে গেছেন বলে মনে করেন।
জিম বাল্টার

লিগ্যাসি ম্যাথের সাথে ধারাবাহিকতার জন্য la ক্ল্যাম্প বাস্তবায়নের জন্য, ন্যূনতম / সর্বাধিক পরামিতিগুলির Clamp(T value, T min, T max)
ক্রমটি


4

কেবলমাত্র লি'র সমাধান মন্তব্যগুলির সমস্যা এবং উদ্বেগের সাথে ভাগ করা , যেখানে সম্ভব:

public static T Clamped<T>(this T value, T min, T max) where T : IComparable<T> {
    if (value == null) throw new ArgumentNullException(nameof(value), "is null.");
    if (min == null) throw new ArgumentNullException(nameof(min), "is null.");
    if (max == null) throw new ArgumentNullException(nameof(max), "is null.");
    //If min <= max, clamp
    if (min.CompareTo(max) <= 0) return value.CompareTo(min) < 0 ? min : value.CompareTo(max) > 0 ? max : value;
    //If min > max, clamp on swapped min and max
    return value.CompareTo(max) < 0 ? max : value.CompareTo(min) > 0 ? min : value;
}

পার্থক্য:

সীমাবদ্ধতা: কোনও একতরফা বাতা নেই। যদি থাকে maxতবে NaNসর্বদা ফিরে আসে NaN( হারমানের মন্তব্য দেখুন )।


আর একটি সীমাবদ্ধতা হ'ল nameofসি # 5 বা নীচের জন্য কাজ করে না।
RoLYroLLs

0

পূর্ববর্তী উত্তরগুলি ব্যবহার করে, আমি এটি আমার প্রয়োজনের জন্য নীচের কোডে নিচে ঘনীভূত করেছি। এটি আপনাকে কেবল তার ন্যূনতম বা সর্বাধিক দ্বারা কোনও সংখ্যা বাতাতেও অনুমতি দেবে।

public static class IComparableExtensions
{
    public static T Clamped<T>(this T value, T min, T max) 
        where T : IComparable<T>
    {
        return value.CompareTo(min) < 0 ? min : value.ClampedMaximum(max);
    }

    public static T ClampedMinimum<T>(this T value, T min)
        where T : IComparable<T>
    {
        return value.CompareTo(min) < 0 ? min : value;
    }

    public static T ClampedMaximum<T>(this T value, T max)
        where T : IComparable<T>
    {
        return value.CompareTo(max) > 0 ? max : value;
    }
}

কেন হবে না return value.ClampedMinimum(min).ClampedMaximum(max);?
হেনরিক

0

নীচের কোডটি কোনও ক্রমে (যেমন bound1 <= bound2, বা bound2 <= bound1) নির্দিষ্টকরণের সীমাগুলি সমর্থন করে । লিনিয়ার সমীকরণগুলি ( y=mx+b) যেখানে লাইনটির opeালু বৃদ্ধি বা হ্রাস হতে পারে সেগুলি থেকে গণনা করা মানগুলিতে ক্ল্যাম্পিংয়ের জন্য আমি এই দরকারীটি পেয়েছি ।

আমি জানি: কোডটিতে পাঁচটি অতি-কুরুচিপূর্ণ শর্তসাপেক্ষ এক্সপ্রেশন অপারেটর রয়েছে । জিনিসটি হ'ল এটি কাজ করে এবং নীচের পরীক্ষাগুলি এটি প্রমাণ করে। আপনি যদি চান তবে কঠোরভাবে অপ্রয়োজনীয় প্রথম বন্ধনী যুক্ত করুন।

আপনি অন্যান্য সংখ্যার ধরণের জন্য খুব সহজেই অন্যান্য ওভারলোডগুলি তৈরি করতে পারেন এবং মূলত পরীক্ষাগুলি অনুলিপি / আটকান।

সতর্কতা: ভাসমান পয়েন্ট সংখ্যাগুলির তুলনা করা সহজ নয়। এই কোডটি doubleদৃ comp়তার সাথে তুলনা কার্যকর করে না । তুলনা অপারেটরগুলির ব্যবহারগুলি প্রতিস্থাপন করতে একটি ফ্লোটিং পয়েন্ট তুলনা লাইব্রেরি ব্যবহার করুন।

public static class MathExtensions
{
    public static double Clamp(this double value, double bound1, double bound2)
    {
        return bound1 <= bound2 ? value <= bound1 ? bound1 : value >= bound2 ? bound2 : value : value <= bound2 ? bound2 : value >= bound1 ? bound1 : value;
    }
}

xUnit / ফ্লুয়েন্টসেসরেশন পরীক্ষা:

public class MathExtensionsTests
{
    [Theory]
    [InlineData(0, 0, 0, 0)]
    [InlineData(0, 0, 2, 0)]
    [InlineData(-1, 0, 2, 0)]
    [InlineData(1, 0, 2, 1)]
    [InlineData(2, 0, 2, 2)]
    [InlineData(3, 0, 2, 2)]
    [InlineData(0, 2, 0, 0)]
    [InlineData(-1, 2, 0, 0)]
    [InlineData(1, 2, 0, 1)]
    [InlineData(2, 2, 0, 2)]
    [InlineData(3, 2, 0, 2)]
    public void MustClamp(double value, double bound1, double bound2, double expectedValue)
    {
        value.Clamp(bound1, bound2).Should().Be(expectedValue);
    }
}

0

যদি আমি [কমপক্ষে, সর্বাধিক] মধ্যে একটি আর্গুমেন্টের সীমাটি বৈধ করতে চাই, তবে আমি নীচের সহজ শ্রেণিটি ব্যবহার করি:

public class RangeLimit<T> where T : IComparable<T>
{
    public T Min { get; }
    public T Max { get; }
    public RangeLimit(T min, T max)
    {
        if (min.CompareTo(max) > 0)
            throw new InvalidOperationException("invalid range");
        Min = min;
        Max = max;
    }

    public void Validate(T param)
    {
        if (param.CompareTo(Min) < 0 || param.CompareTo(Max) > 0)
            throw new InvalidOperationException("invalid argument");
    }

    public T Clamp(T param) => param.CompareTo(Min) < 0 ? Min : param.CompareTo(Max) > 0 ? Max : param;
}

ক্লাসটি যাবতীয় অবজেক্টের জন্য কাজ করে IComparable। আমি একটি নির্দিষ্ট পরিসীমা সহ একটি উদাহরণ তৈরি করি:

RangeLimit<int> range = new RangeLimit<int>(0, 100);

আমি হয় একটি যুক্তি বৈধ

range.Validate(value);

বা ব্যাপ্তিটি পরিসীমাটিতে ক্ল্যাম্প করুন:

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