jjzjj

java - 在 O(N) 时间内更改小数的基数

coder 2024-03-04 原文

我道歉。这个问题是编程作业的一部分。我们被要求实现 一种以 P 位精度将 分数 f 从基数 A 更改为基数 B 的方法。 函数有签名

baseChanger(int[] f, int A, int B, int P)

例如,小数 3.14159 的小数为 0.14159,表示为数组:

int[] frac = {1,4,1,5,9};

16 进制的分数 -- 0.3BA07 -- 会被写成

int[] frac = {3,11,10,0,7};

二进制小数 0.01 转换为十进制小数是 0.25,测试转换函数如下所示:

int[] from = {0,1};
int[] to = {2,5};

@Test
    assertArrayEquals(to, baseChanger(from, 2, 10, 2));

这是我们被要求实现的算法:

/*      
 * for (i < P) {
 *   1. Keep a carry, initialize to 0.
 *   2. From right to left:
 *      a. x = multiply the ith digit by B and add the carry
 *      b. the new ith digit is x % A
 *      c. carry = x / A
 *   3. output[i] = carry 
 * 
 * @param f The input array to translate. This array is not mutated.
 * @param A The base that the input array is expressed in.
 * @param B The base to translate into.
 * @param P The number of digits of precision the output should
 *                   have.
 * @return An array of size P expressing digits in B.
 */

所以对于上面的“from”和“to”,这意味着执行以下操作:

  1. 创建一个可以容纳 P 个数字的数组:

    int[] output = new int[P];//输出 = {0, 0}

  2. 取“from”最右边的数字:

    {0, 1 <==>

  3. 将该数字乘以 B(此处为 10)并加上进位(当前为零),然后分配给 x:

    x <-- 1="" x="" 10="" +="" 0="">

  4. 将最右边的数字(当前为 1)替换为 x mod A(此处为 2):

    {0, 0 <==>

  5. 计算进位,即 x/A:

    携带 <-- 10/2="">

  6. 将进位分配给输出中的第 0 个槽:

    输出[0] <>

    输出:{5 <==,>

这个过程再重复一次,现在输出

output: {2,5}

但是请注意,数字的顺序是错误的,并且是从least significantmost significant 输出的!

此外,(更重要的是)将小数(如 0.3)转换为二进制会怎样做?假设您想要 12 位精度。当然,没有精确的二进制表示法,所以您会在这里做什么,特别是因为最低有效数字出现?

from = {3}

我不确定从哪里开始,希望得到一些建议。请记住,这些数字是分数,而不是整数,并且算法必须在线性 时间内完成。

最佳答案

免责声明:认为它在O(N) 时间内完成。我已经增加了算法的多功能性。此外,负基数是不切实际的

以下方法将十进制数转换为 radix 中提到的数:

/**
 * This method returns an array with <code>precs</code> elements conating the
 * required fractional part in the base <code>radix</code>
 *
 * @param frac A <code>float</code> that contains the fractional part 
 * (and fractional part only!!) in decimal number system.
 * @param radix The base to which it has to be converted (must be (+) ve).
 * @param precs The number of digits required i.e. precision.
 * 
 * @return A <code>int[]</code> that contains the digits(eqivalent).
 */
public static int[] toRadix(float frac, int radix, int precs)
{
    if(radix < 2) return null;
    //Only fractional part is accepted here.
    frac = frac - (long)frac;  //Precautionary measure :-)
    int i, j;
    int[] res = new int[precs]; //For storing result.
    for(i = 0; i < precs && frac != 0; i++)
    {
        frac *= radix;
        res[i] = (int)frac;
        if((long)frac >= 1)
            frac = frac - (long)frac;
    }
    if(flag)
        return copy(res, i);
    return res;
}

将基数 radix 中的数字转换为十进制的方法 -- 返回 float

/**
 * This method returns a <code>float</code> that contains the equivalent of the
 * fraction in the other base in the parameter array, in decimal.
 * 
 * @param frac An <code>int[]</code> conatining only the fractional part.
 * @param radix The base of the fraction entered (must be (+) ve).
 * 
 * @return The equivalent decimal fraction as a <code>float</code>.
 */
public static float toDecimal(int[] frac, int radix)
{
    if(radix < 2) return null;
    float res = 0, fac = 1.0f/radix;
    int i, p = frac.length;
    for(i = 0; i < p; i++)
    {
        res += frac[i] * fac;        //or (float)Math.pow(radix, -i);
        fac/=radix;                  //would be fine as well.
    }
    return res;
}

终于! `baseChanger()` 方法

public static int[] baseChanger(int[] f, int A, int B, int P)
{
    if(A < 2) return null;
    if(B < 2) return null;
    return toRadix(toDecimal(f, A), B, P);
}

复制方法:

private static int[] copy(int[] a, int index)
{
    index = index < a.length ? index : a.length;
    int b[] = new int[index];
    for(int i = 0; i < index; i++)
        b[i] = a[i];
    return b;
}

我已获得所需的泛化水平。结果:

  1. 实际(正确)输出:

  2. 以上编写代码的输出:

所以,我想这就解决了!顺便说一句,这里有一些提示:

  1. 使用数组而不是 String 会导致几个 并发症。对于初学者来说,float 的组成部分 进去很难对付。这个方法ok 对于小数部分,因为我们知道循环应该在哪里 停止。

  2. 使用 String 排除了复制的需要。

  3. 但是您的方法有一个优势:radix 的上限是
    Integer.MAX_VALUEString 方法只有 36(0 到 9 和一个到 z)(虽然这不是一个非常重要的优势,因为它没有实际应用)。

  4. 更改数字基数的最实用方法是首先转换为 十进制和然后,将其转换为其他基数。

  5. 使用 double 会比使用 float 更好,因为它可以提高准确性。

关于java - 在 O(N) 时间内更改小数的基数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21058476/

有关java - 在 O(N) 时间内更改小数的基数的更多相关文章

  1. ruby-on-rails - Ruby on Rails 迁移,将表更改为 MyISAM - 2

    如何正确创建Rails迁移,以便将表更改为MySQL中的MyISAM?目前是InnoDB。运行原始执行语句会更改表,但它不会更新db/schema.rb,因此当在测试环境中重新创建表时,它会返回到InnoDB并且我的全文搜索失败。我如何着手更改/添加迁移,以便将现有表修改为MyISAM并更新schema.rb,以便我的数据库和相应的测试数据库得到相应更新? 最佳答案 我没有找到执行此操作的好方法。您可以像有人建议的那样更改您的schema.rb,然后运行:rakedb:schema:load,但是,这将覆盖您的数据。我的做法是(假设

  2. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  3. ruby - Capistrano 3 在任务中更改 ssh_options - 2

    我尝试使用不同的ssh_options在同一阶段运行capistranov.3任务。我的production.rb说:set:stage,:productionset:user,'deploy'set:ssh_options,{user:'deploy'}通过此配置,capistrano与用户deploy连接,这对于其余的任务是正确的。但是我需要将它连接到服务器中配置良好的an_other_user以完成一项特定任务。然后我的食谱说:...taskswithoriginaluser...task:my_task_with_an_other_userdoset:user,'an_othe

  4. java - 等价于 Java 中的 Ruby Hash - 2

    我真的很习惯使用Ruby编写以下代码:my_hash={}my_hash['test']=1Java中对应的数据结构是什么? 最佳答案 HashMapmap=newHashMap();map.put("test",1);我假设? 关于java-等价于Java中的RubyHash,我们在StackOverflow上找到一个类似的问题: https://stackoverflow.com/questions/22737685/

  5. ruby-on-rails - Ruby 检查日期时间是否为 iso8601 并保存 - 2

    我需要检查DateTime是否采用有效的ISO8601格式。喜欢:#iso8601?我检查了ruby​​是否有特定方法,但没有找到。目前我正在使用date.iso8601==date来检查这个。有什么好的方法吗?编辑解释我的环境,并改变问题的范围。因此,我的项目将使用jsapiFullCalendar,这就是我需要iso8601字符串格式的原因。我想知道更好或正确的方法是什么,以正确的格式将日期保存在数据库中,或者让ActiveRecord完成它们的工作并在我需要时间信息时对其进行操作。 最佳答案 我不太明白你的问题。我假设您想检查

  6. ruby-on-rails - 将 Ruby 中的日期/时间格式化为 YYYY-MM-DD HH :MM:SS - 2

    这个问题在这里已经有了答案:Railsformattingdate(4个答案)关闭4年前。我想格式化Time.Now函数以显示YYYY-MM-DDHH:MM:SS而不是:“2018-03-0909:47:19+0000”该函数需要放在时间中.现在功能。require‘roo’require‘roo-xls’require‘byebug’file_name=ARGV.first||“Template.xlsx”excel_file=Roo::Spreadsheet.open(“./#{file_name}“,extension::xlsx)xml=Nokogiri::XML::Build

  7. ruby - 查找字符串中的内容类型(数字、日期、时间、字符串等) - 2

    我正在尝试解析一个CSV文件并使用SQL命令自动为其创建一个表。CSV中的第一行给出了列标题。但我需要推断每个列的类型。Ruby中是否有任何函数可以找到每个字段中内容的类型。例如,CSV行:"12012","Test","1233.22","12:21:22","10/10/2009"应该产生像这样的类型['integer','string','float','time','date']谢谢! 最佳答案 require'time'defto_something(str)if(num=Integer(str)rescueFloat(s

  8. ruby - 更改 ActiveRecord 中对象的类 - 2

    假设我有一个FireNinja我的数据库中的对象,使用单表继承存储。后来才知道他真的是WaterNinja.将他更改为不同的子类的最干净的方法是什么?更好的是,我很想创建一个新的WaterNinja对象并替换旧的FireNinja在数据库中,保留ID。编辑我知道如何创建新的WaterNinja来self现有FireNinja的对象,我也知道我可以删除旧的并保存新的。我想做的是改变现有项目的类别。我是通过创建一个新对象并执行一些ActiveRecord魔法来替换行,还是通过对对象本身做一些疯狂的事情,或者甚至通过删除它并使用相同的ID重新插入来做到这一点,这是问题的一部分。

  9. java - 从 JRuby 调用 Java 类的问题 - 2

    我正在尝试使用boilerpipe来自JRuby。我看过guide从JRuby调用Java,并成功地将它与另一个Java包一起使用,但无法弄清楚为什么同样的东西不能用于boilerpipe。我正在尝试基本上从JRuby中执行与此Java等效的操作:URLurl=newURL("http://www.example.com/some-location/index.html");Stringtext=ArticleExtractor.INSTANCE.getText(url);在JRuby中试过这个:require'java'url=java.net.URL.new("http://www

  10. java - 我的模型类或其他类中应该有逻辑吗 - 2

    我只想对我一直在思考的这个问题有其他意见,例如我有classuser_controller和classuserclassUserattr_accessor:name,:usernameendclassUserController//dosomethingaboutanythingaboutusersend问题是我的User类中是否应该有逻辑user=User.newuser.do_something(user1)oritshouldbeuser_controller=UserController.newuser_controller.do_something(user1,user2)我

随机推荐