Skip to main content

Sasa.Numbers - Generic Number Extensions

This is the sixth post in my ongoing series covering the abstractions in Sasa. Previous posts:

The Sasa.Numbers static class provides a number of useful extensions methods on all of the CLR's number types. It is available in the core Sasa.dll.

Sasa.Numbers.UpTo

Generating a sequence of numbers is a pretty common operation in programming, so there's a special overload extension called Sasa.Numbers.UpTo:

// iseq = 1, 2, 3
IEnumerable<int> iseq = 1.UpTo(end: 4);
// iseq2 = 1, 3, 5, 7
IEnumerable<int> iseq2 = 1.UpTo(end: 8, step: 2);
// dseq = 5.0, 5.5, 6.0, 6.5, 7.0
IEnumerable<double> dseq = 5.0.UpTo(end: 7.5, step: 0.5);

The simplest overload simply takes the inclusive lower and exclusive upper bounds for the sequence, and the second overload additionally takes a step size designating the increment between each number emitted.

These are defined as generic methods which make use of Sasa.Operators<T>, Sasa's generic operators class.

Sasa.Numbers.DownTo

Sasa.Numbers.DownTo is the complement to Sasa.Numbers.UpTo, where instead of generating a sequence of increasing numbers, it generates a sequence of decreasing numbers:

// iseq = 4, 3, 2
IEnumerable<int> iseq = 4.DownTo(end: 1);
// iseq2 = 8, 6, 4, 2
IEnumerable<int> iseq2 = 8.DownTo(end: 1, step: 2);
// dseq = 7.5, 7.0, 6.5, 6.0, 5.5
IEnumerable<double> dseq = 7.5.DownTo(end: 5.0, step: 0.5);

The simplest overload simply takes the inclusive upper and exclusive lower bounds for the sequence, and the second overload additionally takes a step size designating the decrement between each number emitted.

These are defined as generic methods which make use of Sasa.Operators<T>, Sasa's generic operators class.

Sasa.Numbers.Bound

The Sasa.Numbers.Bounds extension method ensures that a value falls between lower and upper inclusive limits:

int x = 3.Bound(0, 5);          // x=3
int y = 99.Bound(0, 5);         // y=5
double z = 3.0.Bound(4.4, 5.7); // z=4.4

This is defined as a generic method which makes use of Sasa.Operators<T>, Sasa's generic operators class.

Sasa.Numbers.Max

The Sasa.Numbers.Max extension method returns the larger between two arguments it's given:

int x = Numbers.Max(3, 88);        // x=88
decimal d = Numbers.Max(234M, 8M); // d=234M

This is defined as a generic method which makes use of Sasa.Operators<T>, Sasa's generic operators class.

Sasa.Numbers.Min

The complement to Max, the Sasa.Numbers.Min extension method returns the smaller of two arguments:

int x = Numbers.Min(3, 88);        // x=3
decimal d = Numbers.Min(234M, 8M); // d=8M

This is defined as a generic method which makes use of Sasa.Operators<T>, Sasa's generic operators class.

Sasa.Numbers.ToSentence

The Sasa.Numbers.ToSentence method converts an integer to its English sentence representation:

var list = new[] { 3, 99, -99, int.MinValue };
foreach (var x in list)
{
   Console.WriteLine(Numbers.ToSentence(x));
}
// outputs:
// Three
// Ninety Nine
// Minus Ninety Nine
// Minus Two Billion One Hundred Fourty Seven Million Four Hundred Eighty Three Thousand Six Hundred Fourty Eight

Comments

Popular posts from this blog

async.h - asynchronous, stackless subroutines in C

The async/await idiom is becoming increasingly popular. The first widely used language to include it was C#, and it has now spread into JavaScript and Rust. Now C/C++ programmers don't have to feel left out, because async.h is a header-only library that brings async/await to C! Features: It's 100% portable C. It requires very little state (2 bytes). It's not dependent on an OS. It's a bit simpler to understand than protothreads because the async state is caller-saved rather than callee-saved. #include "async.h" struct async pt; struct timer timer; async example(struct async *pt) { async_begin(pt); while(1) { if(initiate_io()) { timer_start(&timer); await(io_completed() || timer_expired(&timer)); read_data(); } } async_end; } This library is basically a modified version of the idioms found in the Protothreads library by Adam Dunkels, so it's not truly ground bre

Building a Query DSL in C#

I recently built a REST API prototype where one of the endpoints accepted a string representing a filter to apply to a set of results. For instance, for entities with named properties "Foo" and "Bar", a string like "(Foo = 'some string') or (Bar > 99)" would filter out the results where either Bar is less than or equal to 99, or Foo is not "some string". This would translate pretty straightforwardly into a SQL query, but as a masochist I was set on using Google Datastore as the backend, which unfortunately has a limited filtering API : It does not support disjunctions, ie. "OR" clauses. It does not support filtering using inequalities on more than one property. It does not support a not-equal operation. So in this post, I will describe the design which achieves the following goals: A backend-agnostic querying API supporting arbitrary clauses, conjunctions ("AND"), and disjunctions ("OR"). Implemen

Easy Automatic Differentiation in C#

I've recently been researching optimization and automatic differentiation (AD) , and decided to take a crack at distilling its essence in C#. Note that automatic differentiation (AD) is different than numerical differentiation . Math.NET already provides excellent support for numerical differentiation . C# doesn't seem to have many options for automatic differentiation, consisting mainly of an F# library with an interop layer, or paid libraries . Neither of these are suitable for learning how AD works. So here's a simple C# implementation of AD that relies on only two things: C#'s operator overloading, and arrays to represent the derivatives, which I think makes it pretty easy to understand. It's not particularly efficient, but it's simple! See the "Optimizations" section at the end if you want a very efficient specialization of this technique. What is Automatic Differentiation? Simply put, automatic differentiation is a technique for calcu