C语言函数:编程世界的魔法钥匙(2)-学习笔记

引言

注:由于这部分内容比较抽象,而小编我又是一个刚刚进入编程世界的计算机小白,所以我的介绍可能会有点让人啼笑皆非。希望大家多多包涵!万分感谢!待到小编我学有所成,一定会把这块知识点重新介绍一遍,让大家更好地理解和掌握。

在上一篇文章中,我们一同探索了函数的基本概念,为深入理解编程中的函数世界打下了坚实基础。现在,让我们继续前行,走进函数递归与迭代的奇妙领域。


1、函数递归

想象一下,你要计算一个非常大的数的阶乘,有没有一种神奇的方法,可以让一个函数自己调用自己来完成这个复杂的计算呢?这里就需要使用我们接下来所要介绍的知识——函数递归

1.1 什么是函数递归?

函数递归是计算机编程中一种非常强大且富有技巧性的概念。
 
从定义上来说,函数递归指的是在函数的定义中使用函数自身的调用
 
通俗来讲,就是一个函数在执行过程中直接或间接地调用了自身。
 

函数递归通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解,只需要少量的程序就可以描述出解题过程所需要的多次重复计算,大大减少了程序的代码量。

函数递归的主要思想:把大事化小

举一个生活中的例子:

想象一下你有一堆俄罗斯套娃。打开最大的那个套娃,里面还有一个小一点的套娃,打开这个小套娃,又有一个更小的。一直这样开下去,(递)直到开到最小的那个套娃,没办法再开了(这就相当于递归的终止条件)。然后再把打开的套娃一个一个地按照原来的顺序放回去。(归)

                      图一                                                                 图二

图二呢就像是我们所编写的代码,在程序未运行起来之前,展现给我们的只是少量代码。

 代码解释:比如说我们有一个递归函数,它的任务是计算某个数的阶乘。

int factorial(int n)
{
    if (n == 0 || n == 1) 
    {
        return 1;
    }
    else 
    {
        return n * factorial(n - 1);
    }
}

首先,factorial(4) 发现 4 不等于 0 也不等于 1,所以它要去计算 4 * factorial(3) 。这就相当于打开了一个稍微小一点的“套娃”,即 factorial(3) 。

然后 factorial(3) 又发现 不符合结束条件,所以要计算 3 * factorial(2) ,这又打开了一个更小的“套娃” factorial(2) 

以此类推,一直到 factorial(1) 或 factorial(0) ,这就相当于我们打开到了最小的那个“套娃”,因为它们会直接返回 1 ,不再继续递归调用。

然后再从最小的“套娃”开始,逐步返回计算结果,一层一层地“合上套娃”,最终得到 factorial(4) 的结果。

就像俄罗斯套娃一样,不断深入打开更小的,最后又从最小的开始一层一层关闭回来,得到最终的结果。

完整代码:

#include <stdio.h>

int factorial(int n)
{
    if (n == 0 || n == 1)//限制条件不可少
    {
        return 1;
    }
    else
    {
        return n * factorial(n - 1);
    }
}
int main()
{
    int num = 4;
    int result = factorial(num);
    printf("阶乘 %d 的结果是 %d\n", num, result);
    return 0;
}

下面用图片来解释:

图片文字较小,建议放大观看!!(如有错误,希望各位大佬指正,万分感谢!!!) 

阶乘的定义是,对于非负整数 n,n 的阶乘(记作 n!)等于 n 乘以 (n - 1) 的阶乘,并且 0 的阶乘和 1 的阶乘都规定为 1。

在函数递归计算阶乘的过程中,我们定义一个函数 factorial 。

当 n 等于 0 或者 1 时,这就是递归的终止条件,因为 0 的阶乘和 1 的阶乘都已经明确规定为 1 了,所以此时函数直接返回 1 。

当 n 大于 1 时,函数就会调用自己来计算 (n - 1) 的阶乘,然后将 n 乘以这个结果,从而得到 n 的阶乘。

 这道题我们要计算 4 的阶乘。函数 factorial(4) 被调用,因为 4 大于 1 ,所以它会返回 4 * factorial(3) 。接着计算 factorial(3) ,又会返回 3 * factorial(2) ,以此类推,一直到 factorial(1) ,因为 1 满足限制条件,所以返回 1 ,然后再逐步回溯计算,最终得到 4 的阶乘的值 24 。 这就是通过函数递归计算阶乘的基本原理它通过不断地自我调用,逐步逼近终止条件,最终得出结果。

到这里大家大致应该对函数递归有一点了解了吧!

上文中我提到了终止条件,这也是函数递归必不可少的条件

1.2 函数递归的两个必要条件

  • 存在 终止条件,当满足这个限制条件的时候,递归就会停止。
  • 每次递归调用之后越来越接近这个限制条件。
 if (n == 0 || n == 1)限制条件

为什么说终止条件是必不可少的呢?

你可以想象一下,一辆火车如果没有刹车,那会是什么情况,是不是停不下来?

终止条件就像是一个“刹车”,如果没有它,函数会不停地调用自身,导致无限循环,最终程序可能会因为栈溢出等错误而崩溃。因此,终止条件可以有效的防止代码的无限循环。

举个例子来说明一下:顺序打印每个数

#include <stdio.h>
void print(unsigned int n)
{
    if (n > 9)//限制条件
    {
       print(n / 10);
    }
      printf("%d", n % 10);   
}
int main()
{
    unsigned int num = 0;
    scanf("%u", &num);
    print(num);//
    return 0;
}

如果将 if (n > 9)这行代码删除会发生什么呢?

当没有限制条件后,这个函数就会自己调自己,一直循环,发生死递归,出现堆栈溢出

1.3  什么叫堆栈溢出呢?

内存划分为栈区、堆区、静态区。

在程序运行时,当一个函数被调用时,会在栈区为该函数分配一块内存空间,用于存储函数的参数、局部变量以及函数执行的上下文信息。

堆栈溢出是由于程序在运行时对栈空间的需求超过了其所能提供的容量,通常是由于不合理的函数调用结构、过大的局部数据或错误的代码逻辑引起的。

我们可以调试看一下

在调试过程中,系统会给这样一个错误,stack overflow叫 栈溢出

      这道题出现栈溢出的原因就是因为该函数没有终止条件,出现死递归导致栈空间被持续占用而无法释放。

这就是为什么我们需要终止条件的原因。

以下是一些避免栈溢出错误的常见方法:

1. 优化函数调用 : 减少函数的嵌套调用层数,避免不必要的深层递归。对于可以使用迭代解决的问题,优先选择迭代而不是递归。

2.控制函数局部变量的大小 :避免在函数内部创建过大的局部数组或其他大型数据结构。如果需要较大的存储空间,可以考虑在堆上动态分配内存。

3. 分解复杂函数 : 将复杂的函数拆分成多个较小的、更简单的函数,以减少单个函数的复杂性和所需的栈空间。

4. 尾递归优化 : 如果使用递归,尽量将其转化为尾递归形式。一些编译器可以对尾递归进行优化,避免栈空间的不断增长。

5. 增加栈空间大小 :在某些编程环境中,可以通过设置来增加栈的默认大小。但这只是一种临时的解决方案,不是根本的解决办法。

6. 数据结构优化 : 选择更合适的数据结构和算法,以减少计算过程中的内存需求和函数调用次数。

7. 检查代码逻辑 ; 确保代码没有进入无限循环或不正确的递归逻辑,导致栈空间不断被消耗。 通过以上方法的综合运用,可以有效地降低出现栈溢出错误的风险,提高程序的稳定性和性能。

相信大家现在应该对终止条件的重要性有一定的了解了吧 ! ! !

1.4 对比求解阶乘

常规循环方法:

#include <stdio.h>

int fac(int n) 
{
    int result = 1;
    for (int i = 1; i <= n; i++)
    {
        result *= i;
    }
    return result;
}

int main()
{
    int num = 0;
    scanf("%d", &num);
    int result = fac(num);
    printf("fac = %d\n", result);
    return 0;
}

在这个常规的循环方法中,通过一个 for 循环从 1 乘到指定的数 n ,逐步累乘得到阶乘的结果。 

函数递归方法:

#include <stdio.h>

int fac(int n)
{
    if (n == 0 || n == 1)//限制条件不可少
    {
        return 1;
    }
    else
    {
        return n * fac(n - 1);
    }
}
int main()
{
    int num = 0;
    scanf("%d", &num);
    int result = fac(num);
    printf("fac = %d\n", result);
    return 0;
}

在递归方法中,如果 n 为 0 或 1 ,直接返回 1 作为终止条件。否则,通过 n 乘以 n - 1 的阶乘来实现递归计算。

对比来看:

代码简洁性:递归方法的代码通常更简洁,更能直接体现阶乘的数学定义。

理解难度:对于初学者,循环方法可能更容易理解,因为它的执行过程更直观。递归方法需要理解函数的自我调用和终止条件,相对较难。

性能:在大多数情况下,循环方法的性能通常比递归方法好,因为递归会带来额外的函数调用开销和栈空间的使用。

适用场景:对于一些具有明显递归结构的问题,递归方法可能更自然和直观;而对于简单的计算,循环方法可能更实用。

1.5 函数递归的优缺点

 优点:

1. 代码简洁性 :递归能够以一种简洁而直观的方式表达某些问题的解决方案,使代码更具可读性和表达力。

2. 符合问题的自然逻辑: 对于一些本身具有递归性质的问题,如树形结构的遍历、某些数学计算等,使用递归更贴合问题的本质逻辑。

3. 易于理解和实现复杂问题:在处理一些复杂问题时,递归可以使解决方案的思路更加清晰,更容易理解和编码。

 缺点:

1. 性能开销 :递归调用会带来额外的函数调用开销,包括参数传递、保存和恢复上下文等,这可能导致性能下降,特别是在递归深度较大时。

2. 栈空间消耗: 每次递归调用都会在栈上分配内存来保存函数的状态和局部变量。如果递归深度过大,可能会导致栈溢出错误。

3. 可读性挑战: 对于一些复杂的递归逻辑,如果没有清晰的注释和良好的设计,可能会使代码难以理解和维护。

4. 调试困难:由于递归调用的复杂性,调试递归函数可能比调试普通函数更具挑战性。 综上所述,在使用函数递归时,需要根据具体问题的特点和需求,权衡其优缺点,以决定是否采用递归方法来解决问题。

1.6 函数递归的实际应用

函数递归在现实生活中有以下一些用处:

1. 组织架构管理 : 公司或机构的组织架构可以看作是一个树形结构。通过递归可以遍历整个架构,例如查找特定部门下的所有子部门和员工。

2. 物流与供应链 :在复杂的物流网络中,确定货物从源头到目的地的所有可能路径时可以使用递归。

3. 任务分解与规划 : 将一个大型项目分解为多个子项目,每个子项目又可以进一步分解,类似于递归的过程,以更好地管理和安排工作。

4. 决策树分析 : 例如在金融领域,分析投资决策的各种可能结果和分支。

5. 人工智能中的搜索算法 :如在棋类游戏的 AI 中,通过递归搜索可能的走法和局面。

6. 语法解析 :在自然语言处理中,对句子的语法结构进行解析时可能用到递归。

7. 目录和文件系统操作 : 遍历计算机中的文件夹和子文件夹,执行特定的操作,如查找特定类型的文件或计算文件大小。

8. 电路设计 : 分析复杂的电路连接和信号传递路径。

9. 数学教育与解题 : 帮助理解和解决一些数学问题,如数列的计算、组合数学中的问题等。

2、函数迭代

函数迭代是通过循环结构来重复执行某段代码,实现问题的解决或计算的过程。

循环是一种迭代,但迭代不仅仅是循环。

2.1 什么是函数迭代

函数迭代指的是将一个初始值代入一个函数,得到一个新的值,然后再将这个新值作为输入再次代入同一个函数,如此反复进行,以获得一系列的值或者逼近某个特定的结果。 简单来说,就是按照一定的规则,不断地用函数作用于某个值,产生新的值,并持续这个过程。

2.2 函数递归与迭代

例题:求第n个斐波那契数(不考虑溢出)

斐波那契数列

1 1 2 3 5 8 13  21 34 55...

大家有看出什么规律吗?

斐波那契数列就是 前两个数相加等于第三个数

了解了斐波那契数列,我们可以用函数表示一下

函数递归代码表示:

int count = 0;//全局变量 

int Fib(int n)
{   //在整个流程中,求了多少次第三个斐波那契数
	if (n == 3)
		count++;
	if (n <= 2)
		return 1;
	else
		return Fib(n - 1) + Fib(n - 2);
}
int main()
{
	int n = 0;
	scanf("%d", &n);
	int ret = Fib(n);
	printf("%d\n", ret);
	printf("%d\n", count);
	return 0;
}

在这个代码里,新加入了一个全局变量 count ,该变量在该循环中是的作用在整个流程中,求了多少次 Fib(3),比如说我们要求Fib(40),代码结果展示:

我们在求第40位斐波那契数的过程中,第三位斐波那契数被求了39088169次,三千多万次

效率低下,并且在使用 fib 这个函数的时候如果我们要计算第50个斐波那契数字的时候特别耗费时间。这是为什么呢?

其实在使用递归求结果的时候,递归程序会不断的展开,在展开的过程中,我们很容易就能发现,在递归的过程中会有大量的重复计算,⽽且递归层次越深,冗余计算就会越多。

函数迭代代码表示:

int Fib(int n)
{   
	int a = 1;
	int b = 1;
	int c = 0;
	while (n >= 3)
	{
		c = a + b;
		a = b;
		b = c;
		n--;
	}
	return c;

结果展示:

从该视频我们就可以看到函数迭代的效率比函数递归求斐波那契数快很多倍,但是由于会出现栈溢出问题,因此在求结果可能会不正确。不过呢,你不要管它对不对,快不快就完事了!!

函数迭代是为了解决重复操作的问题。当我们需要重复执行一段代码,但每次执行都需要不同的输入或参数时,使用函数迭代可以简化代码并提高效率。

通过使用函数迭代,我们可以定义一个函数,并通过不同的输入值多次调用该函数。这样可以避免重复编写相同的代码,提高代码的重用性和可维护性。

另外,函数迭代还可以帮助我们处理大规模数据集,特别是在数据处理和分析方面。通过使用迭代函数,我们可以逐个处理数据集中的元素,而不需要一次性加载整个数据集到内存中。

总之,函数迭代是一种有效的编程技术,可以提高代码的可重用性和可维护性,同时还可以处理大规模数据集。

2.3 函数迭代相较于函数递归的优点:

1.性能优势

函数迭代通常比递归具有更好的性能。因为递归涉及函数的多次调用,会带来额外的开销,而迭代通过循环实现,效率通常更高。

2.内存使用更高效

递归可能导致大量的栈空间使用,容易出现栈溢出错误。迭代一般在固定的内存区域操作,对内存的使用更可控。

3.更易理解和调试

对于一些复杂的递归逻辑,理解和跟踪其执行过程可能较为困难。迭代的执行流程通常更直观,便于调试和查找问题。

4.可扩展性

在处理大规模数据或复杂问题时,迭代更容易进行优化和扩展,例如通过并行化或分段处理来提高效率。

5.不受递归深度限制

递归存在深度限制,而迭代没有这个限制,可以处理更大规模的计算。

3、 避免堆栈溢出的有效方法:

1.精简函数和代码逻辑

优化函数内部的实现,去除不必要的复杂计算和临时变量,使函数执行所需的栈空间减少。

2.限制递归深度

如果使用递归,明确设置递归的最大深度,并在达到限制时采取适当的措施,如返回默认值或错误提示。

3.优化数据结构

选择更节省空间的数据结构。例如,能用指针代替数组的情况尽量使用指针,或者使用具有动态扩展能力的数据结构(如std::vector在 C++中)。

4.合理分配内存

对于较大的数据块,使用堆内存分配(如malloc/new)而不是在栈上分配。并且在使用完毕后及时释放(free/delete)。

5.分治法

将大型任务分解为较小的子任务,分别处理,避免单个函数或操作需要过大的栈空间。

6.控制循环次数和范围

确保循环不会无限制地运行,并且循环的范围是合理的,不会导致过多的栈空间消耗。

7.利用缓存和重用

对于重复计算或频繁使用的数据,进行缓存,避免重复计算和占用额外的栈空间。

总之,要综合考虑程序的设计、算法选择、数据结构和资源管理等多方面因素,以有效地避免堆栈溢出问题。


结语:

亲爱的读者们,本文即将告一段落。首先,我想向大家表示诚挚的歉意我原本以为自己能够清楚地解析函数递归与迭代的概念,然而我错了。在写作过程中,我深感函数递归与迭代的复杂性超乎我的预料。尤其是当我试图解释迭代时,我甚至产生了放弃的念头,因为我觉得自己无法再向前推进。然而,考虑到我已经付出了很多努力,我不愿意就此放弃,所以我还是决定坚持把文章写完。

我知道这篇文章可能没有完全达到大家的期望,我在此深感遗憾。请大家相信,我并非故意如此,只是我在这个领域的知识还有待提高。将来,我会投入更多的时间和精力,争取为大家带来更加深入、易于理解的函数递归与迭代解析。请大家拭目以待,也欢迎随时向我提出建议和意见。

最后,再次向大家表示由衷的歉意,希望你们能够理解我的困境。谢谢你们的支持,我会继续努力,为大家呈现更优质的内容。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/843481.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

零基础STM32单片机编程入门(十五) DHT11温湿度传感器模块实战含源码

文章目录 一.概要二.DHT11主要性能参数三.DHT11温度传感器内部框图四.DTH11模块原理图五.DHT11模块跟单片机板子接线和通讯时序1.单片机跟DHT11模块连接示意图2.单片机跟DHT11模块通讯流程与时序 六.STM32单片机DHT11温度传感器实验七.CubeMX工程源代码下载八.小结 一.概要 DH…

ubuntu20.04支持win10远程桌面连接

1. 安装xrdp sudo apt install xrdp 2. 检查xrdp状态 sudo systemctl status xrdp 要处于running状态 3.&#xff08;若为Ubuntu 20&#xff09;添加xrdp至ssl-cert sudo adduser xrdp ssl-cert 4. 重启服务 sudo systemctl restart xrdp 5. window 远程桌面连接&am…

“信息科技风险管理”和“IT审计智能辅助”两个大模块的部分功能详细介绍:

数字风险赋能中心简介 数字风险赋能中心简介 &#xff0c;时长05:13 大家好&#xff01;我是AI主播安欣&#xff0c;我给大家介绍一下数字风险赋能中心。 大家都知道当前我国政企机构的数字化转型已经进入深水区&#xff0c;数字化转型在给我们带来大量创新红利的同时&#xf…

【BUG】已解决:requests.exceptions.ProxyError: HTTPSConnectionPool

已解决&#xff1a;requests.exceptions.ProxyError: HTTPSConnectionPool 目录 已解决&#xff1a;requests.exceptions.ProxyError: HTTPSConnectionPool 【常见模块错误】 原因分析 解决方案 欢迎来到英杰社区https://bbs.csdn.net/topics/617804998 欢迎来到我的主页&am…

PostgreSQL创建表和自增序列

一、创建表&#xff1a; 注意&#xff1a; 1、在mysql没有序列的概念&#xff0c;id自增通过auto_increment实现&#xff1b; 2、pgsql没有auto_increment的概念&#xff0c;如何实现id自增&#xff1f;有两种方式&#xff1a; 方式一&#xff1a;创建序列&#xff0c;绑定…

Flink HA

目录 Flink HA集群规划 环境变量配置 masters配置 flink-conf.yaml配置 测试 Flink HA集群规划 FLink HA集群规划如下&#xff1a; IP地址主机名称Flink角色ZooKeeper角色192.168.128.111bigdata111masterQuorumPeerMain192.168.128.112bigdata112worker、masterQuorumPee…

Django 请求和响应

1、请求 &#xff08;1&#xff09;get请求 用户直接在浏览器输入网址&#xff0c;参数直接在url中携带 http://127.0.0.1:8000/login/?a1&b%221243%22 &#xff08;2&#xff09;post请求 在html使用post,login.html <!DOCTYPE html> <html lang"en&…

SpringBoot框架学习笔记(三):Lombok 和 Spring Initailizr

1 Lombok 1.1 Lombok 介绍 &#xff08;1&#xff09;Lombok 作用 简化JavaBean开发&#xff0c;可以使用Lombok的注解让代码更加简洁Java项目中&#xff0c;很多没有技术含量又必须存在的代码&#xff1a;POJO的getter/setter/toString&#xff1b;异常处理&#xff1b;I/O…

java学习---小项目---租房系统

package com.project.House_rental.HouseApp;import com.project.House_rental.HouseView.HouseView; //主界面 public class HouseApp {public static void main(String[] args) {new HouseView().List_();System.out.println("------已退出----------");} }package…

PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动?

&#x1f345;关注博主&#x1f397;️ 带你畅游技术世界&#xff0c;不错过每一次成长机会&#xff01;&#x1f4da;领书&#xff1a;PostgreSQL 入门到精通.pdf 文章目录 PostgreSQL 中如何解决因大量并发删除和插入操作导致的索引抖动一、理解索引抖动二、索引抖动的影响三…

Postgresql主键自增的方法

Postgresql主键自增的方法 一.方法&#xff08;一&#xff09; 使用 serial PRIMARY KEY 插入数据 二.方法&#xff08;二&#xff09; &#x1f388;边走、边悟&#x1f388;迟早会好 一.方法&#xff08;一&#xff09; 使用 serial PRIMARY KEY 建表语句如下&#xf…

react中组件间的通信

一、父传子 1.代码展示 import React, { useState } from react;function SonPage(props){ // 子组件const {msg} propsreturn (<div>我是子组件 {msg}</div>) }function App() { // 父组件const [msgText,setMsgText] useState(父传子)return (<div classN…

没有GPU就运行不了了吗?为什么生成的小游戏中什么都没有呀?

原来报错说是没有cuda&#xff0c;于是使用了GPU版本的tensorflow1.15&#xff0c;在主函数中加了下面的语句。 但但是还是 怎么办&#xff1f;

73、Flink 的 DataStream API 生产实践总结

0、汇总 1.可以使用 Maven 命令、CURL 命令、IDEA 手动创建 Flink 项目&#xff1b;2.可以使用 Maven Shade 插件将必需的依赖项打包进应用程序 jar 中&#xff1b;3.应该在 Flink 集群的 lib 文件夹内配置需要的&#xff08;核心&#xff09;依赖项&#xff1b;4.应该将程序中…

游戏常用运行库安装包 Game Runtime Libraries Package

游戏常用运行库安装包&#xff08;Game Runtime Libraries Package&#xff09;是一个整合了多种游戏所需运行库的安装程序&#xff0c;旨在帮助玩家和开发者解决游戏无法正常运行的问题。该安装包支持从Windows XP到Windows 11的系统&#xff0c;并且具备自动检测系统并推荐合…

持续集成07--Jenkins配置Allure测试报告

前言 在持续集成&#xff08;CI&#xff09;流程中&#xff0c;自动化测试报告是评估软件质量和追踪问题的重要工具。Allure Framework作为一个轻量级且功能丰富的测试报告工具&#xff0c;能够生成详细的测试报告&#xff0c;帮助团队更好地理解测试结果。本章节“持续集成07-…

springboot打jar包,部署linux,resource文件夹下的文件读取不到

目录 一、在windows10上可以正常执行 二、在linux上可行的方法 三、报错信息如下 就这一个小问题&#xff0c;困扰了我24H......可能还有更优解&#xff0c;欢迎讨论 一、在windows10上可以正常执行 以下3种方法均可以在windows10上正常使用&#xff0c;可以根据自己爱好&…

上海斯歌受邀出席CDIE2024数字化创新博览会,荣获优秀数字化技术服务商大奖!

6月25至26日&#xff0c;第十届CDIE数字化创新博览会在上海张江科学会堂盛大开幕&#xff0c;作为BPM领域头部品牌的上海斯歌应邀出席大会&#xff0c;与来自全国各地的行业专家们共同交流数字化创新的技术及业务经验。此外&#xff0c;为表彰上海斯歌对行业做出的卓越贡献&…

全面了解不同GPU算力型号的价格!

这两年人工智能&#xff08;AI&#xff09;、机器学习&#xff08;ML&#xff09;、深度学习和高性能计算&#xff08;HPC&#xff09;领域的快速发展&#xff0c;GPU算力已成为不可或缺的资源。企业、研究机构乃至个人开发者越来越依赖于GPU加速计算来处理大规模数据集和复杂模…

3D 渲染一个房屋需要多长时间?

3D 渲染一个房屋总共需要 6-10 个工作日&#xff0c;主要取决于项目的复杂性和最终 3D 渲染的质量&#xff0c;图像越逼真&#xff0c;效果图渲染所需时间就越长。 1.3D建模 创建 3D 模型是第一步&#xff0c;所需时间可能因项目的复杂程度而有很大差异。一个简单的住宅渲染可…