用于连续半部分的无限序列的 Linq 语句

发布于 2025-01-08 02:29:55 字数 163 浏览 1 评论 0原文

给定一个起始数,想象一下它的连续两半的无限序列。

1, 0.5, 0.25, 0.125, ...

(忽略 double 固有的任何数值不稳定性。)

是否可以在单个表达式中完成此操作,而无需编写任何自定义扩展方法或生成器方法?

Given a starting number, imagine an infinite sequence of its successive halves.

1, 0.5, 0.25, 0.125, ...

(Ignore any numerical instabilities inherent in double.)

Can this be done in a single expression without writing any custom extension methods or generator methods?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

扶醉桌前 2025-01-15 02:29:55

我不知道单表达式方式,但我在这里找到了这个聪明的生成器代码: http:// /csharpindepth.com/articles/Chapter11/StreamingAndIterators.aspx

public static IEnumerable<TSource> Generate<TSource>(TSource start,
                                                  Func<TSource,TSource> step)
{
   TSource current = start;
   while (true)
   {
       yield return current;
       current = step(current);
   }
}

在您的情况下,您将使用它:

foreach (double d in Generate<double>(1, c => c / 2))
{
    ...
}

I don't know of a single-expression way but I found this clever generator code here: http://csharpindepth.com/articles/Chapter11/StreamingAndIterators.aspx

public static IEnumerable<TSource> Generate<TSource>(TSource start,
                                                  Func<TSource,TSource> step)
{
   TSource current = start;
   while (true)
   {
       yield return current;
       current = step(current);
   }
}

In your case you'd use it:

foreach (double d in Generate<double>(1, c => c / 2))
{
    ...
}
不疑不惑不回忆 2025-01-15 02:29:55

为了好玩,这里有一个在单个表达式中创建真正的无限序列的技巧。前两个定义是类字段,因此它们不需要初始化表达式。

double? helper;
IEnumerable<double> infinite;

infinite = new object[] { null }.SelectMany(dummy => new double[] { (helper = (helper / 2) ?? 1).Value }.Concat(infinite));

For fun, here's a trick to create a real infinite sequence in a single expression. The first two definitions are class fields, so that they do not require an expression to be initialised.

double? helper;
IEnumerable<double> infinite;

infinite = new object[] { null }.SelectMany(dummy => new double[] { (helper = (helper / 2) ?? 1).Value }.Concat(infinite));
2025-01-15 02:29:55

这是类似于 @hvd 提供的答案,但使用 Y 运算符定义 此处,这消除了对局部变量的需要:

public static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f)
{
    return t => f(Y(f))(t);
}

var halves = Y<double, IEnumerable<double>>(self => d => new[] { 0d }.SelectMany(_ => new[] { d }.Concat(self(d / 2))));

一个示例用法是:

foreach (var half in halves(20))
    Console.WriteLine(half);

它将输出 20, 10, 5, 2.5 等...

我不建议在生产代码中使用它,但它很有趣。

Y 运算符还允许其他递归 lambda 表达式,例如:

var fibonacci = Y<int, int>(self => n => n > 1 ? self(n - 1) + self(n - 2) : n);
var factorial = Y<int, int>(self => n => n > 1 ? n * self(n - 1) : n);
var hanoi = Y<int, int>(self => n => n == 1 ? 1 : 2 * self(n - 1) + 1);

Here is an answer similar to the one @hvd provided, but using the Y operator defined here, this removes the need for the local variables:

public static Func<A, R> Y<A, R>(Func<Func<A, R>, Func<A, R>> f)
{
    return t => f(Y(f))(t);
}

var halves = Y<double, IEnumerable<double>>(self => d => new[] { 0d }.SelectMany(_ => new[] { d }.Concat(self(d / 2))));

An example use would be:

foreach (var half in halves(20))
    Console.WriteLine(half);

Which would output 20, 10, 5, 2.5 etc...

I wouldn't advise using this in production code but it is fun.

The Y operator also allows other recursive lambda expressions, e.g:

var fibonacci = Y<int, int>(self => n => n > 1 ? self(n - 1) + self(n - 2) : n);
var factorial = Y<int, int>(self => n => n > 1 ? n * self(n - 1) : n);
var hanoi = Y<int, int>(self => n => n == 1 ? 1 : 2 * self(n - 1) + 1);
謸气贵蔟 2025-01-15 02:29:55
Enumerable.Repeat(1, int.MaxValue).Select((x, i) => x / Math.Pow(2, i))

它实际上并不是无限的,但由于 RepeatSelect 都使用延迟执行,因此您不会损失任何性能。

不知道任何创建无限 linq 表达式的本机方法。

或者您可以手动编写无限版本的 .Repeat

Enumerable.Repeat(1, int.MaxValue).Select((x, i) => x / Math.Pow(2, i))

It isn't actually infinite, but as both Repeat and Select use deferred execution, you won't lose any performance.

Don't know any native way to create infinite linq expression.

Or you can manually write infinite version of .Repeat

心如狂蝶 2025-01-15 02:29:55

我不知道有什么方法可以直接使用 LINQ 来创建无限序列。但您可以制作一个非常长的序列。

var sequence = Enumerable.Range(0, int.MaxValue)
                         .Select(n => Math.Pow(2, -n));

但是,由于 double 的精度有限,因此在 n 变得太高后,您只会得到零。

I don't know of any way to make an infinite sequence with straight LINQ. But you could make a very long sequence.

var sequence = Enumerable.Range(0, int.MaxValue)
                         .Select(n => Math.Pow(2, -n));

However, since double has finite precision, you'll get nothing but zeroes after n gets too high.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文